java获取异步计算的结果

原创
2018/06/10 16:39
阅读数 3.4K

java Future/Callable/Executors

如何获取一个异步线程的结果呢?使用普通的方法是无法获取异步线程返回结果的,比如继承Thread类、实现Runnable接口这两种方式创建的异步线程是没有返回结果的。

public class Task implements Runnable {
	public void run() {
    
    }
}

run方法是没有返回值,并且无法抛出异常信息。只能在run方法内部直接try...catch处理。并不能throws到外层。

那么,针对这种情况如何处理呢?直接看代码吧。

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

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;


public class FutureTest {
    
    public static void main(String[] args) throws Exception {
        // 创建一个有返回值的异步线程

        // 创建一个线程池
        ExecutorService pool = Executors.newFixedThreadPool(10);  //线程池默认容量为10个线程
        
        MyTask task = new MyTask();

        //pool.execute(task);
        // 提交任务到线程池中,并获取任务返回结果
        /*
        Future<Integer> result = pool.submit(new Callable<Integer>() {
            public Integer call() throws Exception {
                return 100;
            }
        });
        */
        Future<Integer> result = pool.submit(task);

        System.out.println("任务返回结果:" + result.get());  // result.get()会阻塞线程,等待任务执行完毕。

        // 提交任务
        Future<Map<String, Object>> results = pool.submit(new MyTask2());
        Map<String, Object> map = results.get();
        
        System.out.println("map = " + map);


        // 提交任务,这个任务耗时30秒
        
        Future<Map<String, Object>> results3 = pool.submit(new MyTask3());
        try {
            // get(long timeout, TimeUnit unit)  超时时间设置为15秒,15秒还是没返回结果则报超时异常
            Map<String, Object> m = results3.get(15L, TimeUnit.SECONDS);
        } catch (Exception e) {
            System.out.println("任务执行超时了:" + e);
        }
        // 任务执行完毕后关闭线程池,实际应用中,可能不需要关闭线程池。可以一直保持着。
        // 对于超时的任务仍然会等待(比如有一个任务执行了1个小时,但是超时时间设置为15秒,仍然会等到1小时)
        // 直到所有任务执行完毕才关闭线程池
        //pool.shutdown();

        // 立即关闭线程池,不等待任务执行完毕。
        //pool.shutdownNow();

        // 主线程不会等待任务执行完毕才往下走。。但是线程池不会关闭,会一直存在。
        System.out.println("============= main =================");
    }

}

// 任务类
class MyTask implements Callable<Integer> {
    public Integer call() throws Exception {
        return 100;
     }
}

// 任务类2

class MyTask2 implements Callable<Map<String, Object>> {
    public Map<String, Object> call() throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("msg", "成功");
        
        List<String> list = new ArrayList<String>();
        list.add("zhangsan");
        list.add("李四");
        list.add("王五");

        map.put("result", list);
        // 增加一个延迟,模拟执行耗时
        Thread.sleep(2000);

        return map;
    }
}


// 任务类3, 模拟超时,在Future获取任务返回结果的时候设置一个超时时间。
class MyTask3 implements Callable<Map<String, Object>> {
    public Map<String, Object> call() throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("msg", "成功");
        
        List<String> list = new ArrayList<String>();
        list.add("zhangsan");
        list.add("李四");
        list.add("王五");

        map.put("result", list);
        // 增加一个30秒延迟,模拟执行耗时
        Thread.sleep(30000);

        return map;
    }
}

当你的系统有很多任务需要处理的时候使用这种方式很合适,而且还可以设置任务执行的超时时间,不会因为一直等待任务执行而导致主线程等待很久。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部