线程的创建方式及Runnable与Callable的区别
目录
- 线程的创建方式
- 继承 `Thread` 类
- 实现 `Runnable` 接口
- 实现 `Callable` 接口
- `Futrue、Callable、Runnable、FutureTask` 的继承关系
- `Callable` 接口
- `Future` 接口
- `RunnableFuture` 接口
- `FutureTask` 类
- 实现 `Callable` 接口创建线程
- 线程池创建线程
- 线程池创建线程之 `Runnable`
- 线程池创建线程之 `Callable`
- `Runnable` 与 `Callable` 的区别
- `Runnable` 与 `Callable` 的源码
- 文章延伸
- 线程池的 `execute()` 和 `submit()` 区别
线程的创建方式
线程的创建方式
- 继承
Thread
类 - 实现
Runnable
接口 - 实现
Callable
接口 - 线程池创建线程
继承 Thread
类
public class ThreadTest extends Thread {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}public static void main(String[] args) {new ThreadTest().start();new ThreadTest().start();}
}结果:可能每次结果不相同
Thread-0:0
Thread-1:0
Thread-0:1
Thread-1:1
................省略
Thread-1:8
Thread-0:8
Thread-1:9
Thread-0:9
实现 Runnable
接口
public class ThreadTest implements Runnable {@Overridepublic void run() {for (int i = 0; i < 20; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}public static void main(String[] args) {Thread thread1 = new Thread(new ThreadTest());thread1.start();Thread thread2 = new Thread(new ThreadTest());thread2.start();}
}结果:可能每次结果不相同
Thread-0:0
Thread-1:0
Thread-0:1
Thread-1:1
................省略
Thread-0:8
Thread-1:8
Thread-0:9
Thread-1:9
实现 Callable
接口
Futrue、Callable、Runnable、FutureTask
的继承关系
public class FutureTask<V> implements RunnableFuture<V> {}public interface RunnableFuture<V> extends Runnable, Future<V> {void run();
}@FunctionalInterface
public interface Runnable {public abstract void run();
}public interface Future<V> {}
Callable
接口
是一个函数式接口,类泛型参数类型与返回值类型一致,call
方法相当于 Runnable
的 run()
方法,用来写线程的执行任务
@FunctionalInterface
public interface Callable<V> {V call() throws Exception;
}
Future
接口
Callable
接口只是单纯地去获得返回值,但是什么时候获取,或者查看线程的运行状态,就需要借助 Future
。Future
提供了取消任务、获取任务执行的状态与获取结果的能力
public interface Future<V> {// 取消任务的执行,任务已经完成或者已经被取消时,调用此方法,会返回falseboolean cancel(boolean mayInterruptIfRunning);// 判断任务是否被取消boolean isCancelled();// 判断任务是否完成(正常完成、异常以及被取消,都将返回true)boolean isDone();// 阻塞地获取任务执行的结果V get() throws InterruptedException, ExecutionException;// 在一定时间内,阻塞地获取任务执行的结果V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;}
RunnableFuture
接口
从名字上能看出来,RunnableFuture
继承了 Runnable
与 Future
接口,run
方法来自 Runnable
接口
public interface RunnableFuture<V> extends Runnable, Future<V> {void run();
}
以上说的,Runnable、Callable、Future
以及 RunnableFuture
都是接口,真正干活还得靠 FutureTask
FutureTask
类
FutureTask
实现了 RunnableFuture
接口,RunnableFuture
继承了 Runnable
与 Future
接口,因此 FutureTask
既可以作为一个 Runnable
被 Thread
执行,也可以获取到 Future
异步计算的结果
下面看看 FutureTask
类重写 Runnable
接口的 run()
方法
public class FutureTask<V> implements RunnableFuture<V> {public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW; // ensure visibility of callable}public FutureTask(Runnable runnable, V result) {this.callable = Executors.callable(runnable, result);this.state = NEW; // ensure visibility of callable}public void run() {if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {Callable<V> c = callable;if (c != null && state == NEW) {V result;boolean ran;try {// 调用了传入的Callable的Call()方法result = c.call();ran = true;} catch (Throwable ex) {result = null;ran = false;setException(ex);}if (ran)set(result);}} finally {// runner must be non-null until state is settled to// prevent concurrent calls to run()runner = null;// state must be re-read after nulling runner to prevent// leaked interruptsint s = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}}
}
可看出,run()
方法调用了传入的 Callable
的 call()
方法
实现 Callable
接口创建线程
public class CallableFutureTest {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask futureTask = new FutureTask(new Callable() {@Overridepublic Object call() throws Exception {System.out.println(Thread.currentThread().getName());return 200;}});// FutureTask实现了Runnable接口,用Runnable创建一个线程// 注意这里,这里传入futureTask参数,构造了一个Threadnew Thread(futureTask).start();int result = (int) futureTask.get(); // 获取线程的最终结果System.out.println("result的结果:" + result);System.out.println("main come over");}
}结果:
Thread-0
result的结果:200
main come over
线程池创建线程
使用 ThreadPoolExecutor
类中的 execute()
方法来创建线程
关于线程池 ThreadPoolExecutor
类的详情:https://blog.csdn.net/weixin_38192427/article/details/117394526
线程池创建线程之 Runnable
public class ThreadPoolTest {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS,new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 10; i++) {threadPoolExecutor.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});}/*关闭线程池*/threadPoolExecutor.shutdown();while (!threadPoolExecutor.isTerminated()) {}System.out.println("main come over");}
}结果:
pool-1-thread-1
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2
pool-1-thread-1
pool-1-thread-4
pool-1-thread-5
main come over
线程池创建线程之 Callable
public class ThreadPoolTest2 {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS,new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 10; i++) {/*使用FutureTask的构造函数实例化*/FutureTask futureTask = new FutureTask(new Callable() {@Overridepublic Object call() throws Exception {System.out.println(Thread.currentThread().getName());return 200;}});/*由于FutureTask间接的实现了接口Runnable,所以此处可以传递参数futureTask*/threadPoolExecutor.execute(futureTask);}/*关闭线程池*/threadPoolExecutor.shutdown();while (!threadPoolExecutor.isTerminated()) {}System.out.println("main come over");}
}结果:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
main come over
Runnable
与 Callable
的区别
Runnable
与 Callable
的源码
@FunctionalInterface
public interface Runnable {public abstract void run();
}@FunctionalInterface
public interface Callable<V> {V call() throws Exception;
}
Callcble
是有返回值的,返回值是通过实现Future
接口的对象的get
方法获取的,这个方法是会造成线程阻塞的;而Runnable
是没有返回值的,因为Runnable
接口中的run()
方法是没有返回值的Callable
里面的call()
方法是可以抛出异常的,我们可以捕获异常进行处理;但是Runnable
里面的run()
方法是不可以抛出异常的,异常要在run()
方法内部必须得到处理,不能向外界抛出
文章延伸
线程池的 execute()
和 submit()
区别
execute()
方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;execute()
方法的实现是ThreadPoolExecutor
类中
public interface Executor {void execute(Runnable command);
}
submit()
方法用于提交需要返回值的任务。线程池会返回一个Future
类型的对象,通过这个Future
对象可以判断任务是否执行成功,并且可以通过Future
的get()
方法来获取返回值,get()
方法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)
方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完
public interface ExecutorService extends Executor {// ...........................省略<T> Future<T> submit(Runnable task, T result);// ...........................省略
}
public abstract class AbstractExecutorService implements ExecutorService {public Future<?> submit(Runnable task) {if (task == null) throw new NullPointerException();RunnableFuture<Void> ftask = newTaskFor(task, null);execute(ftask);return ftask;}public <T> Future<T> submit(Runnable task, T result) {if (task == null) throw new NullPointerException();RunnableFuture<T> ftask = newTaskFor(task, result);execute(ftask);return ftask;}// ......
}
线程的创建方式及Runnable与Callable的区别相关推荐
- JAVA 三种线程实现创建方式
JAVA 三种线程实现/创建方式 方式一:继承Thread类 通过继承Thread类来创建一个自定义线程类.Thread类本质上就继承了Runable接口,代表一个线程类.启动线程的唯一办法就是通过T ...
- Runnable和Callable的区别:
Runnable和Callable的区别: (1)Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的(2)Callable规定的方法是call(),Runnable规 ...
- java中Runnable和Callable的区别
文章目录 运行机制 返回值的不同 Exception处理 java中Runnable和Callable的区别 在java的多线程开发中Runnable一直以来都是多线程的核心,而Callable是ja ...
- java启动100线程_Java启动新线程的几种方式(Runnable、Callable、CompletableFuture)
一.实现Runnable接口 public classRunnableDemo implements Runnable {public voidrun() {try{ Thread.sleep(100 ...
- Java并发编程(01):线程的创建方式,状态周期管理
本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序 ...
- Java线程的创建方式
文章目录 创建线程的几种方法: ①继承Thread类 ②实现Rullable接口 ③实现Callable接口 Callable接口 Future 接口 FutureTask类 ④使用线程池 Runab ...
- Java 的Runnable和Callable的区别
Runnable和Callable的区别是, (1)Callable规定的方法是call(),Runnable规定的方法是run(). (2)Callable的任务执行后可返回值,而Runnable的 ...
- java 中线程的创建方式
如果说在java中创建线程的有几种方式的话,归根结底我认为就两种方式 1.继承Thread类,重写run方法 继承Thread类,如下图重写了run()方法 通过start()方法来启动线程 最后的输 ...
- Runnable 和 Callable 的区别
区别 两个都是接口,但是 Runnable 方法中 run() 没有声明异常且没有返回值,而 Callable 中 call() 声明了异常且有返回值:(意味着使用 Runnable 需要自己处理异常 ...
- Runnable 与 Callable 的区别
1. 类结构 Runnable: @FunctionalInterface public interface Runnable {public abstract void run(); } Calla ...
最新文章
- python教学反思_Python第3课if教学反思:准备充分承上启下,优化内容模式初显
- day 81 天 ORM 操作复习总结
- 纯php socket mysql_PHP 连接 unix_socket MySQL
- 案例解析|广东自由流收费稽核方案,AI稽核新模式
- IE中如何屏蔽窗口关闭
- BZOJ1853: [Scoi2010]幸运数字(容斥原理)
- 安装centos7的电脑对比视频播放
- Team Foundation Server XXX 不存在,或者此时不可访问:解决方案
- linux上卓懿应用商城王者荣耀键盘映射如何设置?
- mysql 数据库快速入门 数据库的发展
- App Store审核宝典
- 模块化机房建设指导书_模块化机房建设方案
- 微信公众号视频下载教程
- VLOOKUP多条件匹配
- html 隐藏广告代码,js漂浮广告原理 js或者CSS带关闭的漂浮广告代码
- 佐治亚理工计算机科学,Gatech的CS「佐治亚理工学院计算机科学系」
- python 爬虫学习之 selenium.webdriver学习
- 【学习周报9.26 ~ 10.1】Hierarchical Modular Network for Video Captioning(CVPR2022)
- NLP经典论文:Sequence to Sequence、Encoder-Decoder 、GRU 笔记
- 离散数学中Warshall算法简析
热门文章
- 算法: 最大矩形面积85. Maximal Rectangle
- hive出现内存溢出_hive问题处理
- mysql自动跑sql发邮件_SQL server 表数据改变触发发送邮件的方法
- amd玄冰400怎么拆图解_【装机帮扶站】第735期:“无货”当道的京东年底大预售来了(AMD篇)...
- 逻辑斯蒂回归模型为什么用sigmoid函数
- Linux4755文件权限,如何在Linux中管理文件和文件夹的权限
- mysql5.7 字符集编码
- SVM入门(五)线性分类器的求解——问题的描述Part2
- org.apache.hadoop.hbase.mapreduce.Driver 导入数据到HBASE table
- c语言经典面试题 洗牌,网易游戏面试题:如何设计一个公平的洗牌算法