当前位置:网站首页>Callable实现多线程
Callable实现多线程
2022-08-11 03:50:00 【初夏0811】
1.Callable和Runnable
先看一下两个接口的定义:
Callable:
public interface Callable<V> {
V call() throws Exception;
}
Runnable:
interface Runnable {
public abstract void run();
}
明显能看到区别:
1.Callable能接受一个泛型,然后在call方法中返回一个这个类型的值。而Runnable的run方法没有返回值
2.Callable的call方法可以抛出异常,而Runnable的run方法不会抛出异常。
Future
返回值Future也是一个接口,通过他可以获得任务执行的返回值。
定义如下:
public interface Future<V> {
boolean cancel(boolean var1);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}
其中的get方法获取的就是返回值。
下面看下提交一个任务的场景:
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(2);
//创建一个Callable,3秒后返回String类型
Callable myCallable = new Callable() {
@Override
public String call() throws Exception {
Thread.sleep(3000);
System.out.println("calld方法执行了");
return "call方法返回值";
}
};
System.out.println("提交任务之前 "+getStringDate());
Future future = executor.submit(myCallable);
System.out.println("提交任务之后,获取结果之前 "+getStringDate());
System.out.println("获取返回值: "+future.get());
System.out.println("获取到结果之后 "+getStringDate());
}
public static String getStringDate() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
String dateString = formatter.format(currentTime);
return dateString;
}
}
通过executor.submit提交一个Callable,返回一个Future,然后通过这个Future的get方法取得返回值。
运行结果如下:
提交任务之前 12:13:01
提交任务之后,获取结果之前 12:13:01
calld方法执行了
获取返回值: call方法返回值
获取到结果之后 12:13:04
get()方法的阻塞性
通过上面的输出可以看到,在调用submit提交任务之后,主线程本来是继续运行了。但是运行到future.get()的时候就阻塞住了,一直等到任务执行完毕,拿到了返回的返回值,主线程才会继续运行。
这里注意一下,他的阻塞性是因为调用get()方法时,任务还没有执行完,所以会一直等到任务完成,形成了阻塞。
任务是在调用submit方法时就开始执行了,如果在调用get()方法时,任务已经执行完毕,那么就不会造成阻塞。
下面在调用方法前先睡4秒,这时就能马上得到返回值。
System.out.println("提交任务之前 "+getStringDate());
Future future = executor.submit(myCallable);
System.out.println("提交任务之后 "+getStringDate());
Thread.sleep(4000);
System.out.println("已经睡了4秒,开始获取结果 "+getStringDate());
System.out.println("获取返回值: "+future.get());
System.out.println("获取到结果之后 "+getStringDate());
运行如下:
提交任务之前 12:36:04
提交任务之后 12:36:04
calld方法执行了
已经睡了4秒,开始获取结果 12:36:08
获取返回值: call方法返回值
获取到结果之后 12:36:08
可以看到吗,因为睡了4秒,任务已经执行完毕,所以get方法立马就得到了结果。
同样的原因,submit两个任务时,总阻塞时间是最长的那个。
下面看下有多个个任务,一个3秒,一个5秒。
Callable myCallable = new Callable() {
@Override
public String call() throws Exception {
Thread.sleep(5000);
System.out.println("calld方法执行了");
return "call方法返回值";
}
};
Callable myCallable2 = new Callable() {
@Override
public String call() throws Exception {
Thread.sleep(3000);
System.out.println("calld2方法执行了");
return "call2方法返回值";
}
};
System.out.println("提交任务之前 "+getStringDate());
Future future = executor.submit(myCallable);
Future future2 = executor.submit(myCallable2);
System.out.println("提交任务之后 "+getStringDate());
System.out.println("开始获取第一个返回值 "+getStringDate());
System.out.println("获取返回值: "+future.get());
System.out.println("获取第一个返回值结束,开始获取第二个返回值 "+getStringDate());
System.out.println("获取返回值2: "+future2.get());
System.out.println("获取第二个返回值结束 "+getStringDate());
提交任务之前 14:14:47
提交任务之后 14:14:48
开始获取第一个返回值 14:14:48
calld2方法执行了
calld方法执行了
获取返回值: call方法返回值
获取第一个返回值结束,开始获取第二个返回值 14:14:53
获取返回值2: call2方法返回值
获取第二个返回值结束 14:14:53
获取第一个结果阻塞了5秒,所以获取第二个结果立马就得到了。
边栏推荐
- MYSQLg advanced ------ clustered and non-clustered indexes
- 【FPGA】abbreviation
- 一次简单的 JVM 调优,学会拿去写到简历里
- Audio codec, using FAAC to implement AAC encoding
- Leetcode 108. 将有序数组转换为二叉搜索树
- LeetCode刷题第17天之《3 无重复字符的最长子串》
- 元素的BFC属性
- 按摩椅控制板的开发让按摩椅变得简约智能
- 2022-08-10 The sixth group Hiding spring study notes
- The solution to the height collapse problem
猜你喜欢

使用jackson解析json数据详讲

【愚公系列】2022年08月 Go教学课程 035-接口和继承和转换与空接口

Unity2D animation (1) introduction to Unity scheme - animation system composition and the function of use

电商项目——商城限时秒杀功能系统

树莓派入门(5)系统备份

【力扣】22.括号生成

2022-08-10 The sixth group Hiding spring study notes

轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组

云平台下ESB产品开发步骤说明

LeetCode刷题第11天字符串系列之《 58最后一个单词长度》
随机推荐
【FPGA】day18-ds18b20实现温度采集
AI + medical: for medical image recognition using neural network analysis
Element's BFC attribute
获取Qt的安装信息:包括安装目录及各种宏地址
[yu gong series] Go program 035-08 2022 interfaces and inheritance and transformation and empty interface
App基本框架搭建丨日志管理 - KLog
作业8.10 TFTP协议 下载功能
互换性与测量技术-公差原则与选用方法
元素的BFC属性
LeetCode刷题第11天字符串系列之《 58最后一个单词长度》
STC8H开发(十五): GPIO驱动Ci24R1无线模块
VIT 源码详解
C# 一周入门高级编程之《C#-LINQ》Day Four
“顶梁柱”滑坡、新增长极难担重任,阿里“蹲下”是为了跳更高?
[ADI low-power 2k code] Based on ADuCM4050, ADXL363, TMP75 acceleration, temperature detection and serial port printing, buzzer playing music (lone warrior)
互换性测量与技术——偏差与公差的计算,公差图的绘制,配合与公差等级的选择方法
C语言 recv()函数、recvfrom()函数、recvmsg()函数
获取链表长度
App Basic Framework Construction丨Log Management - KLog
程序化交易与主观交易对盈利曲线的影响!