Java中的Runnable,Callable,Future,FutureTask的比较
java中的runnable,callable,future,futuretask的比较
java中存在runnable、callable、future、futuretask这几个与线程相关的类或者接口,在java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。
runnable
其中runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中, 该函数没有返回值 。然后使用某个线程去执行该runnable即可实现多线程,thread类在调用start()函数后就是执行的是runnable的run()函数。runnable的声明如下 :
@functionalinterface public interface runnable { /** * when an object implementing interface <code>runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * the general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.thread#run() */ public abstract void run(); }
callable
callable与runnable的功能大致相似,callable中有一个call()函数,但是 call()函数有返回值 ,而runnable的run()函数不能将结果返回给客户程序。callable的声明如下 :
@functionalinterface 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; }
可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的v类型。
future
executor就是runnable和callable的调度容器,future就是对于具体的runnable或者callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(future简介)。future声明如下:
* @see futuretask * @see executor * @since 1.5 * @author doug lea * @param <v> the result type returned by this future's {@code get} method */ public interface future<v> { /** * attempts to cancel execution of this task. this attempt will * fail if the task has already completed, has already been cancelled, * or could not be cancelled for some other reason. if successful, * and this task has not started when {@code cancel} is called, * this task should never run. if the task has already started, * then the {@code mayinterruptifrunning} parameter determines * whether the thread executing this task should be interrupted in * an attempt to stop the task. * * <p>after this method returns, subsequent calls to {@link #isdone} will * always return {@code true}. subsequent calls to {@link #iscancelled} * will always return {@code true} if this method returned {@code true}. * * @param mayinterruptifrunning {@code true} if the thread executing this * task should be interrupted; otherwise, in-progress tasks are allowed * to complete * @return {@code false} if the task could not be cancelled, * typically because it has already completed normally; * {@code true} otherwise */ boolean cancel(boolean mayinterruptifrunning); /** * returns {@code true} if this task was cancelled before it completed * normally. * * @return {@code true} if this task was cancelled before it completed */ boolean iscancelled(); /** * returns {@code true} if this task completed. * * completion may be due to normal termination, an exception, or * cancellation -- in all of these cases, this method will return * {@code true}. * * @return {@code true} if this task completed */ boolean isdone(); /** * waits if necessary for the computation to complete, and then * retrieves its result. * * @return the computed result * @throws cancellationexception if the computation was cancelled * @throws executionexception if the computation threw an * exception * @throws interruptedexception if the current thread was interrupted * while waiting */ v get() throws interruptedexception, executionexception; /** * waits if necessary for at most the given time for the computation * to complete, and then retrieves its result, if available. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the computed result * @throws cancellationexception if the computation was cancelled * @throws executionexception if the computation threw an * exception * @throws interruptedexception if the current thread was interrupted * while waiting * @throws timeoutexception if the wait timed out */ v get(long timeout, timeunit unit) throws interruptedexception, executionexception, timeoutexception; }
futuretask
futuretask则是一个runnablefuture< v>,而runnablefuture实现了runnbale又实现了futrue< v>这两个接口:
public class futuretask<v> implements runnablefuture<v> { ...... }
runnablefuture
/** * a {@link future} that is {@link runnable}. successful execution of * the {@code run} method causes completion of the {@code future} * and allows access to its results. * @see futuretask * @see executor * @since 1.6 * @author doug lea * @param <v> the result type returned by this future's {@code get} method */ public interface runnablefuture<v> extends runnable, future<v> { /** * sets this future to the result of its computation * unless it has been cancelled. */ void run(); }
另外futuretask还可以包装runnable和callable< v>, 由构造函数注入依赖。
/** * creates a {@code futuretask} that will, upon running, execute the * given {@code callable}. * * @param callable the callable task * @throws nullpointerexception if the callable is null */ public futuretask(callable<v> callable) { if (callable == null) throw new nullpointerexception(); this.callable = callable; this.state = new; // ensure visibility of callable } /** * creates a {@code futuretask} that will, upon running, execute the * given {@code runnable}, and arrange that {@code get} will return the * given result on successful completion. * * @param runnable the runnable task * @param result the result to return on successful completion. if * you don't need a particular result, consider using * constructions of the form: * {@code future<?> f = new futuretask<void>(runnable, null)} * @throws nullpointerexception if the runnable is null */ public futuretask(runnable runnable, v result) { this.callable = executors.callable(runnable, result); this.state = new; // ensure visibility of callable }
可以看到,runnable注入会被executors.callable()函数转换为callable类型,即futuretask最终都是执行callable类型的任务。该适配函数的实现如下 :
/** * returns a {@link callable} object that, when * called, runs the given task and returns the given result. this * can be useful when applying methods requiring a * {@code callable} to an otherwise resultless action. * @param task the task to run * @param result the result to return * @param <t> the type of the result * @return a callable object * @throws nullpointerexception if task null */ 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; } }
由于futuretask实现了runnable,因此它既可以通过thread包装来直接执行,也可以提交给executeservice来执行。并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。
因此futuretask既是future、runnable,又是包装了callable(如果是runnable最终也会被转换为callable ), 它是这两者的合体。
完整示例:
package com.stay4it.rx; 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; import java.util.concurrent.futuretask; public class futuretest { public static class task implements runnable { @override public void run() { // todo auto-generated method stub system.out.println("run"); } } public static class task2 implements callable<integer> { @override public integer call() throws exception { system.out.println("call"); return fibc(30); } } /** * runnable, 无返回值 */ public static void testrunnable(){ executorservice executorservice = executors.newcachedthreadpool(); future<string> future = (future<string>) executorservice.submit(new task()); try { system.out.println(future.get()); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (executionexception e) { // todo auto-generated catch block e.printstacktrace(); } executorservice.shutdown(); } /** * callable, 有返回值 */ public static void testcallable(){ executorservice executorservice = executors.newcachedthreadpool(); future<integer> future = (future<integer>) executorservice.submit(new task2()); try { system.out.println(future.get()); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (executionexception e) { // todo auto-generated catch block e.printstacktrace(); } executorservice.shutdown(); } /** * futuretask则是一个runnablefuture<v>,即实现了runnbale又实现了futrue<v>这两个接口, * 另外它还可以包装runnable(实际上会转换为callable)和callable * <v>,所以一般来讲是一个符合体了,它可以通过thread包装来直接执行,也可以提交给executeservice来执行 * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。 */ public static void testfuturetask(){ executorservice executorservice = executors.newcachedthreadpool(); futuretask<integer> futuretask = new futuretask<integer>(new task2()); executorservice.submit(futuretask); try { system.out.println(futuretask.get()); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (executionexception e) { // todo auto-generated catch block e.printstacktrace(); } executorservice.shutdown(); } /** * futuretask则是一个runnablefuture<v>,即实现了runnbale又实现了futrue<v>这两个接口, * 另外它还可以包装runnable(实际上会转换为callable)和callable * <v>,所以一般来讲是一个符合体了,它可以通过thread包装来直接执行,也可以提交给executeservice来执行 * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。 */ public static void testfuturetask2(){ executorservice executorservice = executors.newcachedthreadpool(); futuretask<integer> futuretask = new futuretask<integer>(new runnable() { @override public void run() { // todo auto-generated method stub system.out.println("testfuturetask2 run"); } },fibc(30)); executorservice.submit(futuretask); try { system.out.println(futuretask.get()); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (executionexception e) { // todo auto-generated catch block e.printstacktrace(); } executorservice.shutdown(); } public static void main(string[] args) { testcallable(); } /** * 效率低下的斐波那契数列, 耗时的操作 * * @param num * @return */ static int fibc(int num) { if (num == 0) { return 0; } if (num == 1) { return 1; } return fibc(num - 1) + fibc(num - 2); } }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇: Request.UrlReferrer中文乱码解决方法
下一篇: 正则表达式速查表(ASP.NET)
推荐阅读
-
Java中的Runnable,Callable,Future,FutureTask的比较
-
简析Java中的util.concurrent.Future接口
-
java中四种操作xml方式的比较
-
java 中ThreadLocal本地线程和同步机制的比较
-
简析Java中的util.concurrent.Future接口
-
Java中的Vector和ArrayList区别及比较
-
关于JAVA中TreeMap集合使用匿名内部类Comparetor自定制比较器排序无法序列化的问题
-
java 中ThreadLocal本地线程和同步机制的比较
-
Java中的Vector和ArrayList区别及比较
-
详解JDK中ExecutorService与Callable和Future对线程的支持