当前位置:网站首页>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秒,所以获取第二个结果立马就得到了。
边栏推荐
- js 将字符串作为js执行代码使用
- MySQL数据库存储引擎以及数据库的创建、修改与删除
- 【FPGA】day22-SPI protocol loopback
- 【FPGA】abbreviation
- The impact of programmatic trading and subjective trading on the profit curve!
- 构建程序化交易系统需要注意什么问题?
- Environment configuration of ESP32 (arduino arduino2.0 VScode platform which is easy to use?)
- 树莓派入门(5)系统备份
- A brief analysis of whether programmatic futures trading or manual order is better?
- 机器学习是什么?详解机器学习概念
猜你喜欢
UNI-APP_iphone苹果手机底部安全区域
CTO说MySQL单表行数不要超过2000w,为啥?
Basic understanding of MongoDB (2)
轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组
【FPGA】day22-SPI protocol loopback
LeetCode刷题第16天之《239滑动窗口最大值》
VIT 源码详解
LeetCode814算题第15天二叉树系列值《814 二叉树剪枝》
Detailed explanation of VIT source code
A simple JVM tuning, learn to write it on your resume
随机推荐
What has programmatic trading changed?
Interchangeable Measurement Techniques - Geometric Errors
uni-app - 获取汉字拼音首字母(根据中文获取拼音首字母)
Docker 链接sqlserver时出现en-us is an invalid culture错误解决方案
MYSQLg advanced ------ clustered and non-clustered indexes
电力机柜数据监测RTU
App基本框架搭建丨日志管理 - KLog
【FPGA】day21- moving average filter
A simple JVM tuning, learn to write it on your resume
Detailed explanation of VIT source code
什么是三方支付?
FTP错误代码列表
你不知道的 console.log 替代品
UNI-APP_iphone bottom safe area
Unity2D animation (1) introduction to Unity scheme - animation system composition and the function of use
80端口和443端口是什么?有什么区别?
LeetCode刷题第17天之《3 无重复字符的最长子串》
STC8H开发(十五): GPIO驱动Ci24R1无线模块
【FPGA】day22-SPI protocol loopback
机器学习可以应用在哪些场景?机器学习有什么用?