zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    onload执行顺序
    让EXCHANGE可以接收外部邮件服务器发送的邮件
    QQ网站里AppTui对象脚本
    owa2007写新邮件时已经选择人员不能带入到与通讯录选人界面问题解决方法
    qq网站里动态加载脚本的实现
    qq网站里对元素的操作方法
    让Exchange可以发送邮件到互联网的邮件服务器
    js实现的hashtable
    无线网卡共享网络发射
    css省略号效果
  • 原文地址:https://www.cnblogs.com/hongdada/p/6120698.html
Copyright © 2011-2022 走看看