FutureTask并发详解,通俗易懂

时间:2022-12-19 16:08:09

最近做项目,使用到了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