FutureTask并发详解,通俗易懂

 

 

最近做项目,使用到了FutureTask和主线程并发,应用到实际中还是挺实用的,特在此总结一下。

有不对之处,忘各位多多指出。

复制代码
复制代码
 1 package com.demo;
 2 
 3 import java.util.concurrent.Callable;
 4 import java.util.concurrent.FutureTask;
 5 
 6 public class FutureTaskTest {
 7 
 8     public static void main(String[] args) throws Exception {
 9         for (int i = 0; i < 10; i++) {
10             long currentTimeMillis = System.currentTimeMillis();
11             FutureTask<String> future1 = new FutureTask<>(new MyTaskA());
12             new Thread(future1).start();// 一定要先开启线程,如果主线程在开启线程前调用,就没了并发的效果,可以自行测试
13             Thread.sleep(100);// 主线程耗时100ms
14             String r1 = future1.get();
15             System.out.println(r1);
16             System.err.println(i + "-----" + String.valueOf(System.currentTimeMillis() - currentTimeMillis) + "ms");
17         }
18     }
19 
20     static class MyTaskA implements Callable<String> {
21         @Override
22         public String call() throws Exception {
23             Thread.sleep(50);// 并发线程耗时50ms
24             return "testA";
25         }
26     }
27 
28 }
复制代码
复制代码

20-26行创建一个任务MyTaskA,实现的是Callable,主要是为了获取返回值(关于如何创建线程,这里就不在赘述);

11行创建FutureTask;

12行启动线程:此时任务MyTaskA就已经开始执行;

13行主线程执行耗时100ms的任务;

14行FutureTask获取返回值,该方法是会等待任务完成然后获取到返回值。

输出结果如下:

复制代码
复制代码
testA
0-----101ms
testA
1-----100ms
testA
2-----100ms
testA
3-----100ms
testA
4-----100ms
testA
5-----100ms
testA
6-----100ms
testA
7-----100ms
testA
8-----100ms
testA
9-----100ms
复制代码
复制代码

上面就是一个线程和主线程并发执行,下面再看一个两个线程和主线程并发,其实差别不大

复制代码
复制代码
 1 package com.demo;
 2 
 3 import java.util.concurrent.Callable;
 4 import java.util.concurrent.FutureTask;
 5 
 6 public class FutureTaskTest {
 7     
 8     public static void main(String[] args) throws Exception{
 9         for (int i = 0; i < 10; i++) {
10             long currentTimeMillis = System.currentTimeMillis();
11             
12             FutureTask<String> futureA = new FutureTask<>(new MyTaskA()); 
13             FutureTask<String> futureB = new FutureTask<>(new MyTaskB()); 
14             new Thread(futureA).start();
15             new Thread(futureB).start();
16             
17             Thread.sleep(100);
18             System.out.println(futureA.get()+"---"+futureB.get());
19             System.err.println(i+"-----"+String.valueOf(System.currentTimeMillis()-currentTimeMillis)+"ms");
20         }
21     }
22     static class MyTaskA implements Callable<String>{
23         @Override
24         public String call() throws Exception {
25             Thread.sleep(50);//并发线程耗时50ms
26             return "testA";
27         }
28     }
29     static class MyTaskB implements Callable<String>{
30         @Override
31         public String call() throws Exception {
32             Thread.sleep(50);
33             return "testB";
34         }
35     }
36     
37 
38 }
复制代码
复制代码

执行结果如下

复制代码
复制代码
testA---testB
0-----103ms
testA---testB
1-----100ms
testA---testB
2-----100ms
testA---testB
3-----100ms
testA---testB
4-----100ms
testA---testB
5-----101ms
testA---testB
6-----100ms
testA---testB
7-----101ms
testA---testB
8-----100ms
testA---testB
9-----101ms
复制代码
复制代码

上面使用Thread启动的FutureTask,咱们也可以用线程池,代码如下

复制代码
复制代码
package com.demo;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureTaskTest {

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            long currentTimeMillis = System.currentTimeMillis();
            ExecutorService executorService = Executors.newFixedThreadPool(2);
            Future<String> futureA = executorService.submit(new MyTaskA());
            Future<String> futureB = executorService.submit(new MyTaskB());

            Thread.sleep(100);
            System.out.println(futureA.get() + "---" + futureB.get());
            System.err.println(i + "-----" + String.valueOf(System.currentTimeMillis() - currentTimeMillis) + "ms");
       executorService.shutdown();//注意:用完之后一定要关闭线程池 } } static class MyTaskA implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(50);// 并发线程耗时50ms return "testA"; } } static class MyTaskB implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(50); return "testB"; } } }
复制代码
复制代码

输出结果如下

复制代码
复制代码
testA---testB
0-----104ms
testA---testB
1-----101ms
testA---testB
2-----101ms
testA---testB
3-----101ms
testA---testB
4-----100ms
testA---testB
5-----102ms
testA---testB
6-----101ms
testA---testB
7-----101ms
testA---testB
8-----101ms
testA---testB
9-----101ms
复制代码
复制代码

 

posted @   满Sir  阅读(100)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示