当前位置:网站首页>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秒,所以获取第二个结果立马就得到了。
边栏推荐
- What kind of programming trading strategy types can be divided into?
- 【愚公系列】2022年08月 Go教学课程 036-类型断言
- How to delete statements audit log?
- CTO said that the number of rows in a MySQL table should not exceed 2000w, why?
- 作业8.10 TFTP协议 下载功能
- Paper Accuracy - 2017 CVPR "High-Resolution Image Inpainting using Multi-Scale Neural Patch Synthesis"
- 【FPGA】day20-I2C读写EEPROM
- Design and Realization of Employment Management System in Colleges and Universities
- Qnet Weak Network Test Tool Operation Guide
- MYSQLg高级------聚簇索引和非聚簇索引
猜你喜欢
Is Redis old?Performance comparison between Redis and Dragonfly
LeetCode刷题第16天之《239滑动窗口最大值》
E-commerce project - mall time-limited seckill function system
机器学习怎么学?机器学习流程
一次简单的 JVM 调优,学会拿去写到简历里
CTO said that the number of rows in a MySQL table should not exceed 2000w, why?
Echart地图的省级,以及所有地市级下载与使用
DNS separation resolution and intelligent resolution
【愚公系列】2022年08月 Go教学课程 035-接口和继承和转换与空接口
【FPGA】SDRAM
随机推荐
【愚公系列】2022年08月 Go教学课程 035-接口和继承和转换与空接口
互换性测量与技术——偏差与公差的计算,公差图的绘制,配合与公差等级的选择方法
LeetCode刷题第16天之《239滑动窗口最大值》
浅析一下期货程序化交易好还是手工单好?
【FPGA】SDRAM
UNI-APP_iphone bottom safe area
Qnet弱网测试工具操作指南
树莓派入门(5)系统备份
【ADI低功耗2k代码】基于ADuCM4050的ADXL363、TMP75的加速度、温度检测及串口打印、蜂鸣器播放音乐(孤勇者)
Differences and connections between distributed and clustered
console.log alternatives you didn't know about
一文读懂 高性能可预期数据中心网络
2022-08-10 第六小组 瞒春 学习笔记
程序化交易改变了什么?
What has programmatic trading changed?
80端口和443端口是什么?有什么区别?
Will oracle cardinality affect query speed?
轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组
Element's BFC attribute
【C语言】入门