通过Callable和FutureTask创建线程
一、使用步骤
虽然Runnable接口实现多线程比继承Thread类实现多线程方法要好,但是Runnable接口里的run方法并不能返回操作结果。为了解决这样的矛盾,java提供了Callable接口。
创建并启动有返回值的线程的步骤如下:
- 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值,再创建Callable实现类的实例
- 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值
- 使用FutureTask对象作为Thread对象的target创建并启动新线程
- 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
二、源码
这个接口的源码如下:
@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}
call方法执行完线程的主体功能之后(类似于Runnable的run方法)会返回值,而返回值类型由Callable接口上的泛型决定。
以下是一个定义使用Callable接口的例子,定义了一个线程主体类:
class MyThread implements Callable<String>{private int ticket=10;@Overridepublic String call() throws Exception{for(int i=0;i<200;i++){if(this.ticket>0){System.out.println("ticket="+ticket--);}}return "ticket sold out!";}
}
通过查看源码可以发现Thread类里面没有提供支持Callable接口的多线程应用。
通过继续查看源码可以发现,FutureTask< V >类,这个类主要是负责Callable接口对象操作,这个类的结构定义如下:
public class FutureTask<V> implements RunnableFuture<V>
RunnableFuture接口继承了Runnable接口和Future接口:
public interface RunnableFuture<V> extends Runnable, Future<V> {/*** Sets this Future to the result of its computation* unless it has been cancelled.*/void run();
}
FutureTask类中有如下的构造方法:
/*** Creates a {@code FutureTask} that will, upon running, execute the* given {@code Callable}.** @param callable the callable task* @throws NullPointerException if the callable is null*/public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW; // ensure visibility of callable}
这个构造方法接收Callable接口对象或者继承了Callable接口对象的类,以此使得这个类能接收call方法的返回结果,从而放入值,而FutureTask又间接实现了Runnable接口和Future接口,Future接口的get方法负责取出值。
完整的Callable接口实现多线程的例子如下:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class test {public static void main(String[] args) throws ExecutionException, InterruptedException {MyThread mt1=new MyThread();MyThread mt2=new MyThread();FutureTask<String> task1=new FutureTask<String>(mt1);FutureTask<String> task2=new FutureTask<String>(mt2);//FutureTask是Runnable接口的实现类/子类,所以Thread构造方法可以接收其对象new Thread(task1).start();new Thread(task2).start();//FutureTask同时是Future接口的实现类/子类,父接口的get方法可以获取其值System.out.println("A"+task1.get());System.out.println("B"+task2.get());}
}class MyThread implements Callable<String>{private int ticket=10;@Overridepublic String call() throws Exception{for(int i=0;i<200;i++){if(this.ticket>0){System.out.println("ticket="+ticket--);}}return "ticket sold out!";}
}
输出结果如下:
这种实现方式的麻烦之处在于既要接收返回值信息,并且又要与原始的多线程的实现靠拢。
通过Callable和FutureTask创建线程相关推荐
- Java创建线程的三种方式,以前只知道两种,现在添加一种Callable与FutureTask创建的方式
一共有以下三种方式: 1.继承Thread 2.实现Runnable 3.实现Callable,并FutureTask包装 线程启动方式均是使用start()方法 先阐述优缺点: 1和2,3: 2,3 ...
- 【头歌实训】Java高级特性 - 多线程基础(1)使用线程,使用 Callable 和 Future 创建线程
任务描述 本关任务:通过 Callable 和 Future 来创建线程. 相关知识 从Java1.5版本开始,就提供了 Callable 和 Future 来创建线程,这种方式也是在Java程序员面 ...
- java回调原理,以及Callable和FutureTask通过回调机制创建可监控的线程
回调的概念会JS的人应该都能理解. 回调分异步回调,同步回调.但是同步回调其实没什么意义.都同步了,那么直接等那边执行完了,这边再执行就可以了,没必要通过回调.我们说的回调主要是讲异步回调.用于两个线 ...
- 创建线程的三种方式、线程运行原理、常见方法、线程状态
文章目录 1.创建线程的三种方式 1.1 继承Thread类并重写run方法 1.2 使用Runnable配合Thread 1.3 通过Callable和FutureTask创建线程 2.Runnab ...
- Java多线程 - Java创建线程的4种方式
文章目录 1. Java创建线程有哪几种方式? 1.1 线程创建方法一:继承Thread类创建线程类 1.2 线程创建方法二:实现Runnable接口创建线程目标类 1.5 线程创建方法三:使用Cal ...
- Java基础教程——多线程:创建线程
多线程 进程 每一个应用程序在运行时,都会产生至少一个进程(process). 进程是操作系统进行"资源分配和调度"的独立单位. Windows系统的"任务管理器&quo ...
- 创建线程都有哪些方式?— Callable篇
今天我们来看一道面试题引发的思考 问: 创建线程都有哪些方式? 答: 我了解的有四种创建方式: 继承Thread类创建线程类 通过Runnable接口创建线程类 通过Callable和Future创建 ...
- 创建线程(Lock()、线程池、Callable())及线程通信
package com.xt.java;import java.util.concurrent.locks.ReentrantLock;/*** 解决线程安全问题的方式三:Lock锁 -->JD ...
- 【多线程】采用Callable接口创建线程
前言 java5开始,提供了Callable接口,是Runable接口的增强版.同样用Call()方法作为线程的执行体,增强了之前的run()方法.因为call方法可以有返回值,也可以声明抛出异常. ...
- 创建线程的第三种方式:实现Callable接口(含部分源码解析)
创建线程的第三种方式--实现Callable接口 package com.lqy.Multithreading; import java.util.concurrent.Callable; impor ...
最新文章
- 实现简书个人中心UI效果
- 雪鹰领主服务器维护,《雪鹰领主》7月14日维护更新公告
- kubernetes学习笔记 (二):k8s初体验
- php 命令链模式,设计模式之------命令链模式
- mysql for update_mysql SELECT FOR UPDATE语句使用示例
- 大数据挑战与NoSQL数据库技术pdf
- lamp 测试mysql_搭建LAMP测试环境
- websockets_Websockets在数据工程中鲜为人知的模式
- Inspection工具窗口
- SQLMAP使用教程(一)
- 苹果app旧版本软件下载
- QQ远程提示系统权限原因暂时无法操作怎么办
- dbi与dbd的含义与区别
- 金色十月线上编程比赛第二题:解密
- PCB板用基板材料分类
- 龙瀛:大数据在城市设计中的应用(附演讲视频)
- DialogUtil
- 电信说的几兆带宽和自己看到的下载/上传速度有什么关系
- 开发一个简单的APP到底需要多少钱
- 互联网企业盈利模式全分析二
热门文章
- Flutter之Widget 更新机制updateChild原理浅析
- ImageLoader的简单分析(终结篇)
- 为什么 Flink 无法实时写入 MySQL?
- 弃用 Notepad++,还有5款更牛逼的选择!
- Android 10正式版发布,支持5G和折叠屏设备
- 我用Python又爬虫了拉钩招聘,给你们看看2019市场行情
- dbeaver查看执行计划_SAP学习基础篇(52):PP模块-物料需求计划
- mysql 主从 日志_mysql主从复制基于日志复制
- mysql实现分布式锁_数据库实现分布式锁
- python-gui-pyqt5的使用方法-8--实际案例可参考使用