Java并发包——使用新的方式创建线程
Java并发包——使用新的方式创建线程
摘要:本文主要学习了如何使用Java并发包中的类创建线程。
部分内容来自以下博客:
https://www.cnblogs.com/dolphin0520/p/3949310.html
使用Callable接口创建线程
Callable与Runnable
之前学习多线程的时候,使用java.lang包下的Runnable接口可以创建线程。
1 @FunctionalInterface 2 public interface Runnable { 3 public abstract void run(); 4 }
发现由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。
Callable位于java.util.concurrent包下,它是一个函数式接口,在它里面声明了一个方法,只不过这个方法叫做call()。
1 @FunctionalInterface 2 public interface Callable<V> { 3 V call() throws Exception; 4 }
通过源码可以看到call()方法是一个泛型接口,可以返回V类型的数据,并且支持抛出异常。
Future
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
Future类位于java.util.concurrent包下,它是一个接口:
1 public interface Future<V> { 2 // 用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。 3 // 参数mayInterruptIfRunning表示是否允许取消正在执行的任务,如果设置true,则表示可以取消正在执行过程中的任务。 4 // 如果任务已经完成,返回false。 5 // 如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false。 6 // 如果任务还没有执行,返回true。 7 boolean cancel(boolean mayInterruptIfRunning); 8 9 // 表示正在执行的任务是否被取消成功,如果在完成前被取消成功,返回true。 10 boolean isCancelled(); 11 12 // 表示任务是否已经完成,若任务完成,则返回true。 13 boolean isDone(); 14 15 // 用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回。 16 V get() throws InterruptedException, ExecutionException; 17 18 // 用来获取执行结果,如果在指定时间内,还没获取到结果,就抛出TimeoutException异常。 19 V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; 20 }
因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。
FutureTask
我们先来看一下FutureTask的实现:
1 public class FutureTask<V> implements RunnableFuture<V>
FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:
1 public interface RunnableFuture<V> extends Runnable, Future<V>
可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
FutureTask提供了2个构造器:
public FutureTask(Callable<V> callable);
public FutureTask(Runnable runnable, V result);
创建线程并使用
代码如下:
1 public class Demo { 2 public static void main(String[] args) { 3 FutureTask<Integer> futureTask = new FutureTask<Integer>(new NewFutureTask()); 4 new Thread(futureTask).start(); 5 try { 6 Integer i = futureTask.get(); 7 System.out.println(i); 8 } catch (InterruptedException e) { 9 e.printStackTrace(); 10 } catch (ExecutionException e) { 11 e.printStackTrace(); 12 } 13 } 14 } 15 16 class NewFutureTask implements Callable<Integer> { 17 @Override 18 public Integer call() throws Exception { 19 System.out.println("call() ..."); 20 return 100; 21 } 22 }
运行结果如下:
1 call() ... 2 100
因为FutureTask实现了RunnableFuture接口,而RunnableFuture又继承了Runnable和Future接口,所以FutureTask可以看作是Runnable的一个实现类。
所以在创建线程的时候,代码 new Thread(futureTask).start(); 实际上是通过 public Thread(Runnable target) 方法创建的线程。
使用线程池创建线程
Executor
Executor接口是线程池的顶层接口,ExecutorService接口是Executor的子接口,而ThreadPoolExecutor类实现了ExecutorService接口,是线程池的核心类。
Executors类时线程池的一个工具类,里面提供了创建线程池的几个静态方法。
下面的代码展示了使用Executors类的newFixedThreadPool()方法创建一个固定长度的线程池,并向线程池中插入任务的操作:
1 public class Demo { 2 public static void main(String[] args) { 3 ExecutorService threadPool = Executors.newFixedThreadPool(3); 4 5 for (int i = 1; i <= 11; i++) { 6 DemoThread dt = new DemoThread(i); 7 threadPool.submit(dt); 8 } 9 threadPool.shutdown(); 10 } 11 } 12 13 class DemoThread implements Runnable { 14 int taskNo = 0; 15 16 public DemoThread(int taskNo) { 17 this.taskNo = taskNo; 18 } 19 20 @SuppressWarnings("static-access") 21 public void run() { 22 try { 23 System.out.println("task " + taskNo); 24 Thread.currentThread().sleep(4000); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 }
结果如下:
1 task 1 2 task 3 3 task 2// 此处有等待。 4 task 4 5 task 5 6 task 6// 此处有等待。 7 task 7 8 task 9 9 task 8// 此处有等待。 10 task 10 11 task 11
结果说明:
可以看到因为设置的线程数为3,所以在创建了3个线程之后,将剩下的任务放在了任务队列里,当有任务执行完成之后再将其取出执行。
转载于:https://www.cnblogs.com/shamao/p/11015558.html
Java并发包——使用新的方式创建线程相关推荐
- python线程创建对象_Python使用面向对象方式创建线程实现12306售票系统
目前python 提供了几种多线程实现方式 thread,threading,multithreading ,其中thread模块比较底层,而threading模块是对thread做了一些包装,可以更 ...
- Java多线程学习总结(7)——创建线程池的正确姿势
一. 通过Executors创建线程池的弊端 在创建线程池的时候,大部分人还是会选择使用Executors去创建. 下面是创建定长线程池(FixedThreadPool)的一个例子,严格来说,当使用如 ...
- Runnable方式创建线程详解
2.4创建线程的方式二 创建线程的第二种方式.使用Runnable接口. 该类中的代码就是对线程要执行的任务的定义. 1:定义了实现Runnable接口 2:重写Runnable接口中的run方法,就 ...
- java runnable接口 sleep_java Runnable接口如何创建线程
java Runnable接口如何创建线程 导语:编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互.下面是java Runnable接口创建线程的相关资料,欢迎阅读: java Ru ...
- java thread 多线程_java用Thread方式创建多线程
进程:一个正在执行的程序,每一个进程都有一个执行顺序,该 顺序是一个执行路径,或者叫一个控制单元. 线程:进程中一个独立的控制单元.线程控制着进程的执行. 一个进程中至少有一个线程. java VM中 ...
- Java多线程(6)--Callable接口创建线程
与使用Runnable相比, Callable功能更强大些 ①相比run()方法,可以有返回值 ②方法可以抛出异常 ③支持泛型的返回值 ④需要借助FutureTask类,可以获取返回结果 Future ...
- Java 创建线程的三种方式
一.继承Thread类创建 1.定义一个类继承Thread类,并重写Thread类的run()方法,run()方法的方法体就是线程要完成的任务,因此把run()称为线程的执行体: 2.创建该类的实例对 ...
- Java多线程 - Java创建线程的4种方式
文章目录 1. Java创建线程有哪几种方式? 1.1 线程创建方法一:继承Thread类创建线程类 1.2 线程创建方法二:实现Runnable接口创建线程目标类 1.5 线程创建方法三:使用Cal ...
- java创建线程(Thread)的5种方式
java创建线程(Thread)的5种方式 方式一:继承于Thread类 方式二:实现Runnable接口 方式三:实现Callable接口 方式四:使用线程池 方式五:使用匿名类 方式一:继承于Th ...
最新文章
- 瑞雪时晴,不亦快哉 ——图灵十一月月刊
- 关于ANSI和UTF-8,windows和unix的行结束符
- petalinux zynq spi_ZYNQ 系列 01 | PL 实现按键控制 LED(1)
- SAP本地化-银企直连
- 为什么 MySQL 回滚事务也会导致 ibd 文件增大?
- 1.3编程基础之算术表达式与顺序执行 01 A+B问题
- pyqt5实时动态曲线
- 小米POCO X3今日亮相:首发骁龙732G后置6400万四摄
- 兰亭集势笔试题:用最优方法从LinkedList列表中删除重复元素
- 让网页附件为Word或Excel的文件,下载时直接弹出下载对话框,而不打开它
- 象棋名手手机版2019最新版_象棋名手64核比赛冠军版2019
- Linux使用Wget实现整站下载
- 通过调用百度生成短连接API接口,将长链接转换成短链接,并且生成短网址并返回,用户可以通过短连接访问,然后浏览器会解析跳转至长链接地址,有效的解决用户修改url后面的参数
- thinkpadt410接口介绍_【ThinkPadT410s(2912BR7)评测】丰富接口满足日常所需-中关村在线...
- linux系统连接校园无线网卡,Linux连接校园网
- 将用户需求转成产品需求
- Python数据可视化之南丁格尔玫瑰图
- TCP/UDP 区别
- 第2章 C语言的数值数据与非数值数据 (二)
- 广东省谷歌地球高程DEM等高线下载