• java中FutureTask的使用



    java中FutureTask的使用

    FutureTask简介

    FutureTask是java 5引入的一个类,从名字可以看出来FutureTask既是一个Future,又是一个Task。

    我们看下FutureTask的定义:

    public class FutureTask<V> implements RunnableFuture<V> {
        ...
    }
    
    public interface RunnableFuture<V> extends Runnable, Future<V> {
        /**
         * Sets this Future to the result of its computation
         * unless it has been cancelled.
         */
        void run();
    }
    

    FutureTask实现了RunnableFuture接口,RunnableFuture接口是Runnable和Future的综合体。

    作为一个Future,FutureTask可以执行异步计算,可以查看异步程序是否执行完毕,并且可以开始和取消程序,并取得程序最终的执行结果。

    除此之外,FutureTask还提供了一个runAndReset()的方法, 该方法可以运行task并且重置Future的状态。

    Callable和Runnable的转换

    我们知道Callable是有返回值的,而Runnable是没有返回值的。
    Executors提供了很多有用的方法,将Runnable转换为Callable:

        public static <T> Callable<T> callable(Runnable task, T result) {
            if (task == null)
                throw new NullPointerException();
            return new RunnableAdapter<T>(task, result);
        }
    

    FutureTask内部包含一个Callable,并且可以接受Callable和Runnable作为构造函数:

        public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }
    
        public FutureTask(Runnable runnable, V result) {
            this.callable = Executors.callable(runnable, result);
            this.state = NEW;       // ensure visibility of callable
        }
    

    它的内部就是调用了Executors.callable(runnable, result);方法进行转换的。

    以Runnable运行

    既然是一个Runnable,那么FutureTask就可以以线程的方式执行,我们来看一个例子:

    @Test
        public void convertRunnableToCallable() throws ExecutionException, InterruptedException {
            FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                   log.info("inside callable future task ...");
                    return 0;
                }
            });
    
            Thread thread= new Thread(futureTask);
            thread.start();
            log.info(futureTask.get().toString());
        }
    

    上面例子是以单个线程来执行的,同样我们也可以将FutureTask提交给线程池来执行:

        @Test
        public void workWithExecutorService() throws ExecutionException, InterruptedException {
            FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    log.info("inside futureTask");
                    return 1;
                }
            });
            ExecutorService executor = Executors.newCachedThreadPool();
            executor.submit(futureTask);
            executor.shutdown();
            log.info(futureTask.get().toString());
        }
    

    本文的例子可参考https://github.com/ddean2009/learn-java-concurrency/tree/master/futureTask

    更多教程请参考 flydean的博客

  • 相关阅读:
    spring service层单元测试
    Java源码学习 -- java.lang.StringBuilder,java.lang.StringBuffer,java.lang.AbstractStringBuilder
    Java源码学习 -- java.lang.String
    动态规划算法
    单元测试(Spring)
    Servlet/JSP
    Log4j2 — Log4j2导入、LogEvent、配置文件编写及路径
    idea 控制台输出 中文乱码 解决方法
    常见正则表达式
    读《浪潮之巅》(吴军著)有感
  • 原文地址:https://www.cnblogs.com/flydean/p/12680263.html
Copyright © 2020-2023  润新知