Java并发之Runnable、Callable、Future、FutureTask

作者: 编程应用  发布:2019-09-06
public interface Runnable { public abstract void run();}

接口的区别

public interface Runnable {
    public abstract void run();
}

public interface Callable<V> {
    V call() throws Exception;
}

Callable的代码也特别轻松,分裂的是它是一个泛型接口,call()函数再次来到的品类就是创办Callable传进来的V类型。

Runnable的代码极度轻松,它是两个接口且独有贰个run(),创立二个类完毕它,把有个别谭何轻易操作写在里边,然后选取有个别线程去实施该Runnable完毕类就能够实现二十四线程。

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;
}

Future是二个接口,定义了Future对于现实的Runnable恐怕Callable职责的实践结果实行裁撤、查询义务是还是不是被撤消,查询是或不是产生、获取结果。

public interface Callable<V> { V call() throws Exception;}

Future基本用法:

class MyCallable implements Callable<String>{
    @Override
    public String call() throws Exception {
        System.out.println("做一些耗时的任务...");
        Thread.sleep(5000);
        return "OK";
    }
}

public class FutureSimpleDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        ExecutorService executorService = Executors.newCachedThreadPool();
       //主要是线程池返回的就是这个类型,做了包装。用submit
        Future<String> future = executorService.submit(new MyCallable());
        System.out.println("dosomething...");
        //阻塞等待结果返回
        System.out.println("得到异步任务返回结果:" + future.get());
        System.out.println("Completed!");
    }
}

Future引用对象指向的实际上是FutureTask。

Callable的代码也非常轻易,区别的是它是三个泛型接口,call()函数重返的品类正是创办Callable传进来的V类型。学习Callable相比着Runnable,那样就十分的快能知晓它。Callable与Runnable的功能大致相似,Callable功用庞大一些,便是被线程推行后,能够再次来到值,何况能抛出拾叁分。

FutureTask

FutureTask的父类是RunnableFuture,而RunnableFuture承袭了Runnbale和Futrue那八个接口

public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>

FutureTask构造方法

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
}

FutureTask最后都以实行Callable类型的任务。
设若构造函数参数是Runnable,会被Executors.callable方法调换为Callable类型。

看看Executors.callable方法代码

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

会见RunnableAdapter方法代码

/**
     * A callable that runs given task and returns given result
     */
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }

RunnableAdapter是FutureTask的二个静态内部类而且达成了Callable,也正是说RunnableAdapter是Callable子类。
call方法完成代码是,实行Runnable的run方法,并重临构造FutureTask传入result参数。

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;}

Future是三个接口,定义了Future对于现实的Runnable或许Callable职务的实施结果举办撤销、查询任务是或不是被打消,查询是或不是变成、获取结果。

FutureTask基本用法

public class CallableAndFuture {
    public static void main(String[] args) {
        Callable<Integer> callable = new Callable<Integer>() {
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        };
        FutureTask<Integer> future = new FutureTask<Integer>(callable);
        new Thread(future).start();
        try {
            Thread.sleep(3000);// 可能做一些事情
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

FutureTask达成了多个接口,Runnable和Future,所以它不仅可以够当做Runnable被线程实践,又足以作为Future获得Callable的重临值,那么这么些组成的采用有哪些利润吗?假如有二个很为难逻辑须求总计况且重返那些值,同一时间那些值不是立即必要,那么就足以应用这几个组合,用另三个线程去总计重返值,而近日线程在运用那个重临值在此以前能够做其余的操作,等到需求以此再次回到值时,再经过Future获得!

Ref:
http://www.jianshu.com/p/cf12d4244171

Future基本用法:

class MyCallable implements Callable<String>{ @Override public String call() throws Exception { System.out.println("做一些耗时的任务..."); Thread.sleep; return "OK"; }}public class FutureSimpleDemo { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executorService = Executors.newCachedThreadPool(); Future<String> future = executorService.submit(new MyCallable; System.out.println("dosomething..."); System.out.println("得到异步任务返回结果:" + future.get; System.out.println("Completed!"); }}

地点是Future基本用法的代码以及并运转,大家得以掌握:

  1. 线程是属于异步总计模型,所以你不容许直接从别的线程中得到方法重回值。 那时候,Future就上场了。
  2. Futrue能够监视目的线程调用call的事态,当你调用Future的get()方法以博取结果时,当前线程就从头阻塞,直接call方法停止再次来到结果。
  3. Future引用对象指向的莫过于是FutureTask。

约等于说,总计一句话,Future能够博得其他线程任务措施的重临值。

FutureTask承接结构

FutureTask的父类是RunnableFuture,而RunnableFuture承继了Runnbale和Futrue那多少个接口

public class FutureTask<V> implements RunnableFuture<V> 

public interface RunnableFuture<V> extends Runnable, Future<V> 

FutureTask构造方法

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}

在此处大家得以理解到:

  1. FutureTask最终都以实行Callable类型的职责。
  2. 若是构造函数参数是Runnable,会被Executors.callable方法转换为Callable类型。

接下去我们看看Executors.callable方法代码

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

代码很简短,直接再次回到二个RunnableAdapter实例。

接下去大家看看RunnableAdapter方法代码

 /** * A callable that runs given task and returns given result */ static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }

能够明白到:

  1. RunnableAdapter是FutureTask的一个静态内部类何况达成了Callable,也等于说RunnableAdapter是Callable子类。
  2. call方法实现代码是,实践Runnable的run方法,并赶回构造FutureTask传入result参数。

FutureTask基本用法

public class CallableAndFuture { public static void main(String[] args) { Callable<Integer> callable = new Callable<Integer>() { public Integer call() throws Exception { return new Random().nextInt; } }; FutureTask<Integer> future = new FutureTask<Integer>; new Thread.start(); try { Thread.sleep;// 可能做一些事情 System.out.println(future.get; } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }}

FutureTask总结

FutureTask完成了多个接口,Runnable和Future,所以它不只能够作为Runnable被线程试行,又有什么不可看成Future获得Callable的重临值,那么这么些组成的运用有哪些平价吗?倘诺有三个很费劲逻辑须要总计並且再次回到那个值,同期那么些值不是立刻供给,那么就足以采纳那一个组合,用另一个线程去计算重返值,而眼下线程在动用那些再次回到值在此之前可以做任何的操作,等到要求那么些重临值时,再经过Future获得!

注意:

通过Executor实践线程职务都以以Callable方式,倘诺传入Runnable都会转接为Callable。

由此new Thread,只好是Runnable子类格局。

本文由今晚开什么码发布于编程应用,转载请注明出处:Java并发之Runnable、Callable、Future、FutureTask

关键词:

上一篇:没有了
下一篇:没有了