欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

深入进修 劳务派遣信息管理系统 FutureTask

点击: 次  来源:宝鼎软件 时间:2017-07-29

原文出处: 天凉好个秋

第一部门:What

在Java中一般通过担任Thread类可能实现Runnable接口这两种方法来建设多线程,可是这两种方法都有个缺陷,就是不能在执行完成后获取执行的功效,因此Java 1.5之后提供了Callable和Future接口,通过它们就可以在任务执行完毕之后获得任务的执行功效。本文会扼要的先容利用要领,然后会从源代码角度阐明下详细的实现道理。
本文以Java 1.7的代码举办阐明。

第二部门:How

Callable接口

对付需要执行的任务需要实现Callable接口,Callable接口界说如下:

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

可以看到Callable是个泛型接口,泛型V就是要call()要领返回的范例。Callable接口和Runnable接口很像,都可以被别的一个线程执行,可是正如前面所说的,Runnable不会返回数据也不能抛出异常。

Future接口

Future接口代表异步计较的功效,通过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;
}
  • cancel():cancel()要领用来打消异步任务的执行。假如异步任务已经完成可能已经被打消,可能由于某些原因不能打消,则会返回false。假如任务还没有被执行,则会返回true而且异步任务不会被执行。假如任务已经开始执行了可是还没有执行完成,若mayInterruptIfRunning为true,则会当即间断执行任务的线程并返回true,若mayInterruptIfRunning为false,则会返回true且不会间断任务执行线程。
  • isCanceled():判定任务是否被打消,假如任务在竣事(正常执行竣事可能执行异常竣事)前被打消则返回true,不然返回false。
  • isDone():判定任务是否已经完成,假如完成则返回true,不然返回false。需要留意的是:任务执行进程中产生异常、任务被打消也属于任务已完成,也会返回true。
  • get():获取任务执行功效,假如任务还没完成则会阻塞期待直到任务执行完成。假如任务被打消则会抛出CancellationException异常,假如任务执行进程产生异常则会抛出ExecutionException异常,假如阻塞期待进程中被间断则会抛出InterruptedException异常。
  • get(long timeout,Timeunit unit):带超时时间的get()版本,假如阻塞期待进程中超时则会抛出TimeoutException异常。
  • FutureTask

    Future只是一个接口,不能直接用来建设工具,FutureTask是Future的实现类,
    FutureTask的担任图如下:

    深入学习 劳务调派信息打点系统  FutureTask

    可以看到,FutureTask实现了RunnableFuture接口,则RunnableFuture接口担任了Runnable接口和Future接口,所以FutureTask既能当做一个Runnable直接被Thread执行,也能作为Future用来获得Callable的计较功效。

    利用

    FutureTask一般共同ExecutorService来利用,也可以直接通过Thread来利用。

    package com.beautyboss.slogen.callback;
    
    import java.util.concurrent.*;
    
    /**
     * Author  : Slogen
     * AddTime : 17/6/4
     * Email   : huangjian13@meituan.com
     */
    public class CallDemo {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            /**
             * 第一种方法:Future + ExecutorService
             * Task task = new Task();
             * ExecutorService service = Executors.newCachedThreadPool();
             * Future<Integer> future = service.submit(task1);
             * service.shutdown();
             */
    
    
            /**
             * 第二种方法: FutureTask + ExecutorService
             * ExecutorService executor = Executors.newCachedThreadPool();
             * Task task = new Task();
             * FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
             * executor.submit(futureTask);
             * executor.shutdown();
             */
    
            /**
             * 第三种方法:FutureTask + Thread
             */
    
            // 2. 新建FutureTask,需要一个实现了Callable接口的类的实例作为结构函数参数
            FutureTask<Integer> futureTask = new FutureTask<Integer>(new Task());
            // 3. 新建Thread工具并启动
            Thread thread = new Thread(futureTask);
            thread.setName("Task thread");
            thread.start();
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("Thread [" + Thread.currentThread().getName() + "] is running");
    
            // 4. 挪用isDone()判定任务是否竣事
            if(!futureTask.isDone()) {
                System.out.println("Task is not done");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int result = 0;
            try {
                // 5. 挪用get()要领获取任务功效,假如任务没有执行完成则阻塞期待
                result = futureTask.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            System.out.println("result is " + result);
    
        }
    
        // 1. 担任Callable接口,实现call()要领,泛型参数为要返回的范例
        static class Task  implements Callable<Integer> {
    
            @Override
            public Integer call() throws Exception {
                System.out.println("Thread [" + Thread.currentThread().getName() + "] is running");
                int result = 0;
                for(int i = 0; i < 100;++i) {
                    result += i;
                }
    
                Thread.sleep(3000);
                return result;
            }
        }
    }

    第三部门:Why

    结构函数