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

posted @ 2016-12-01 09:42  hongdada  阅读(1586)  评论(0编辑  收藏  举报