• Java 线程池Future和FutureTask


    Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务。

    Future接口源码:

    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws InterruptedException, ExecutionException;
        V get(long timeout, TimeUnit unit)
                throws InterruptedException, ExecutionException, TimeoutException;
    }
    View Code

    Future的demo

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class Main {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newCachedThreadPool();
            List<Future<String>> resultList = new ArrayList<Future<String>>();
    
            // 创建10个任务并执行
            for (int i = 0; i < 10; i++) {
                // 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
                Future<String> future = executorService.submit(new TaskWithResult(i));
                // 将任务执行结果存储到List中
                resultList.add(future);
            }
            executorService.shutdown();
    
            // 遍历任务的结果
            for (Future<String> fs : resultList) {
                try {
                    System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    executorService.shutdownNow();
                    e.printStackTrace();
                    return;
                }
            }
        }
    }
    class TaskWithResult implements Callable<String> {
        private int id;
    
        public TaskWithResult(int id) {
            this.id = id;
        }
    
        /**
         * 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
         *
         * @return
         * @throws Exception
         */
        public String call() throws Exception {
            System.out.println("call()方法被自动调用,干活!!!             " + Thread.currentThread().getName());
            if (new Random().nextBoolean())
                throw new TaskException("Meet error in task." + Thread.currentThread().getName());
            // 一个模拟耗时的操作
            for (int i = 999999999; i > 0; i--)
                ;
            return "call()方法被自动调用,任务的结果是:" + id + "    " + Thread.currentThread().getName();
        }
    }
    
    class TaskException extends Exception {
        public TaskException(String message) {
            super(message);
        }
    }
    call()方法被自动调用,干活!!!             pool-1-thread-2
    call()方法被自动调用,干活!!!             pool-1-thread-6
    call()方法被自动调用,干活!!!             pool-1-thread-1
    call()方法被自动调用,任务的结果是:0    pool-1-thread-1
    call()方法被自动调用,任务的结果是:1    pool-1-thread-2
    call()方法被自动调用,干活!!!             pool-1-thread-4
    call()方法被自动调用,干活!!!             pool-1-thread-9
    call()方法被自动调用,干活!!!             pool-1-thread-8
    call()方法被自动调用,干活!!!             pool-1-thread-10
    call()方法被自动调用,干活!!!             pool-1-thread-5
    call()方法被自动调用,干活!!!             pool-1-thread-3
    call()方法被自动调用,干活!!!             pool-1-thread-7
    call()方法被自动调用,任务的结果是:2    pool-1-thread-3
    call()方法被自动调用,任务的结果是:3    pool-1-thread-4
    java.util.concurrent.ExecutionException: com.company.TaskException: Meet error in task.pool-1-thread-5
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:192)
        at com.company.Main.main(Main.java:29)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
    Caused by: com.company.TaskException: Meet error in task.pool-1-thread-5
        at com.company.TaskWithResult.call(Main.java:56)
        at com.company.TaskWithResult.call(Main.java:40)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    View Code

    FutureTask是一个具体的实现类,ThreadPoolExecutor的submit方法返回的就是一个Future的实现,这个实现就是FutureTask的一个具体实例,FutureTask帮助实现了具体的任务执行,以及和Future接口中的get方法的关联。

    Demo:

    import java.util.Date;
    import java.text.SimpleDateFormat;
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class Main {
        public static void main(String[] args) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 初始化一个Callable对象和FutureTask对象
            Callable pAccount = new PrivateAccount();
            FutureTask futureTask = new FutureTask(pAccount);
            // 使用futureTask创建一个线程
            Thread pAccountThread = new Thread(futureTask);
            System.out.println("futureTask线程现在开始启动,启动时间为:" + df.format(new Date()));
            pAccountThread.start();
            System.out.println("futureTask线程开始执行其他任务");
            // 从其他账户获取总金额
            int totalMoney = new Random().nextInt(100000);
            System.out.println("现在你在其他账户中的总金额为" + totalMoney);
            System.out.println("等待私有账户总金额统计完毕...");
            // 测试后台的计算线程是否完成,如果未完成则等待
            while (!futureTask.isDone()) {
                try {
                    Thread.sleep(500);
                    System.out.println("私有账户计算未完成继续等待...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("futureTask线程计算完毕,此时时间为" + df.format(new Date()));
            Integer privateAccountMoney = null;
            try {
                privateAccountMoney = (Integer) futureTask.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            System.out.println("您现在的总金额为:" + totalMoney +"||"+privateAccountMoney.intValue());
        }
    }
    
    class PrivateAccount implements Callable {
        Integer totalMoney;
    
        @Override
        public Object call() throws Exception {
            Thread.sleep(5000);
            totalMoney = new Integer(new Random().nextInt(10000));
            System.out.println("您当前有" + totalMoney + "在您的私有账户中");
            return totalMoney;
        }
    }
    futureTask线程现在开始启动,启动时间为:2016-11-30 16:34:57
    futureTask线程开始执行其他任务
    现在你在其他账户中的总金额为17113
    等待私有账户总金额统计完毕...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    私有账户计算未完成继续等待...
    您当前有8776在您的私有账户中
    私有账户计算未完成继续等待...
    futureTask线程计算完毕,此时时间为2016-11-30 16:35:02
    您现在的总金额为:17113||8776
    View Code

    Demo2:

    import java.util.Date;
    import java.text.SimpleDateFormat;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class Main {
        public static void main(String[] args) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            FutureTask<String> futureTask=new FutureTask<>(new Callable<String>() {
                //@Override
                public String call() throws Exception {
                    // TODO Auto-generated method stub
                    return "回调完成";
                }
            });
            Thread thread = new Thread(futureTask);
            System.out.println("启动时间为:" + df.format(new Date()));
            thread.start();
            try {
                String str=futureTask.get();
    
                if(str.equals("回调完成"))
                    System.out.println("异步任务完成!");
                else
                    System.out.println("Completed!");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    启动时间为:2016-12-01 09:37:03
    异步任务完成!
    View Code

    http://ifeve.com/futuretask-source/

    http://www.liuinsect.com/2014/02/17/futuretask-%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/

    http://blog.csdn.net/ghsau/article/details/7451464

    http://blog.csdn.net/javazejian/article/details/50896505

  • 相关阅读:
    Sqli-Labs less46-53
    Sqli-Labs less38-45
    Sqli-Labs less32-37
    移动web问题小结
    伪类与伪元素
    HTML5 视频直播
    判断鼠标移入移出元素时的方向
    Input操作文件
    利用WebStorm来管理你的Github
    webkit开发,app移动前端知识点
  • 原文地址:https://www.cnblogs.com/hongdada/p/6120698.html
Copyright © 2020-2023  润新知