自从Java平台的最开始,Runnable接口就已存在了。它允许你定义一个可由线程完成的任务。
如大多数人所已知的那样,它只提供了一个run方法,该方法既不接受任何参数,也不返回任何值。
如果你需要从一个未完成的任务中返回一个值,你就必须在该接口之外使用一个方法去等待该任务完成时通报的某种消息。
例如,下面的示例就是你在这种情景下可能做的事情:
Runnablerunnable=...;
Threadt=newThread(runnable);
t.start();
<wbr style="line-height:25px">t.join()</wbr><wbr style="line-height:25px">;<br style="line-height:25px"> Stringvalue=someMethodtoGetSavedValue()<br style="line-height:25px"> 严格来说,上述代码并无错误,但现在可用不同的方法去做,这要感谢J2SE5.0引入的Callable接口。<br style="line-height:25px"> 不同于Runnable接口拥有run方法,<wbr style="line-height:25px"><span style="color:#ff00ff; line-height:25px">Callable</span><span style="color:#000080; line-height:25px">接口提供的是call方法,该方法可以返回一个Object对象,</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">或可返回任何一个在泛型化格式中定义了的特定类型的对象</span><wbr style="line-height:25px">。<br style="line-height:25px"> publicinterfaceCallable<V>{<br style="line-height:25px"> Vcall()throwsException;<br style="line-height:25px"> }<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#003366; line-height:25px">因为你不可能把</span><span style="color:#ff6600; line-height:25px">Callable</span><span style="color:#003366; line-height:25px">对象传到</span><span style="color:#ff9900; line-height:25px">Thread</span><span style="color:#003366; line-height:25px">对象去执行,你可换用</span><span style="color:#ff6600; line-height:25px">ExecutorService</span><span style="color:#003366; line-height:25px">对象去执行</span><span style="color:#ff00ff; line-height:25px">Callable</span><span style="color:#003366; line-height:25px">对象。<br style="line-height:25px"> 该服务接受Callable对象,并经由submit方法去执行它。</span><br style="line-height:25px"><span style="line-height:25px"></span><span style="color:#0000ff; line-height:25px"><T>Future<T>submit(</span><span style="color:#ff00ff; line-height:25px">Callable</span><span style="color:#0000ff; line-height:25px"><T>task)</span><wbr style="line-height:25px"><br style="line-height:25px"> 如该方法的定义所示,提交一个Callable对象给ExecutorService会返回一个Future对象。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">然后,Future的get方法将会阻塞,直到任务完成</span><wbr style="line-height:25px">。<br style="line-height:25px"> 为了证明这一点,下面的例子为命令行中的每个词都创建一个单独的Callable实例,然后把这些词的长度加起来。<br style="line-height:25px"> 各个Callable对象将只是计算它自己的词的长度之和。Futures对象的Set集合将被保存以便从中获得计算用的值。<br style="line-height:25px"> 如果需要保持返回值的顺序,则可换用一个List对象。<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.*;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.concurrent.*;</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicclass</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">CallableExample</span><span style="color:#3366ff; line-height:25px">{<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">publicstatic</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#ff9900; line-height:25px">WordLengthCallable</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">implementsCallable{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">privateStringword;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">WordLengthCallable(Stringword){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.word=word;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#808000; line-height:25px">Integer</span><span style="color:#3366ff; line-height:25px">call(){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#99cc00; line-height:25px">Integer</span><span style="color:#3366ff; line-height:25px">.valueOf(word.length());</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">main</span><span style="color:#3366ff; line-height:25px">(Stringargs[])throwsException{</span><br style="line-height:25px"><span style="color:#0000ff; line-height:25px">ExecutorServicepool=Executors.newFixedThreadPool(3);<br style="line-height:25px"> Set<Future<Integer>>set=newHashSet<Future<Integer>>();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">for</span><span style="color:#3366ff; line-height:25px">(Stringword:args){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Callable<Integer>callable=newWordLengthCallable(word);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Future<Integer>future=pool.submit(callable);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(future);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intsum=0;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">for(Future<Integer>future:set){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">sum+=future.get();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">system.out.printf("Thesumoflengthsis%s%n",sum);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">system.exit(sum);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> WordLengthCallable保存了每个词并使用该词的长度作为call方法的返回值。<br style="line-height:25px"> 这个值可能会花点儿时间去生成,不过在这个例子中,可以立即知道它。call方法的唯一要求是这个值要在call方法的结尾处返回。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">当Future的get方法稍后被调用时,如果任务运行得很快的话,Future将会立刻得到这个值(如同本例的情况),否则将一直等到该值生成完毕为止<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"> 对Future的get方法的调用会阻塞当前线程并等待任务结束,而不会阻塞其它的任务和线程。<br style="line-height:25px"> 这个特定的例子使用固定数线程池来产生ExecutorService对象,但其它有效的方法也是可行的。<br style="line-height:25px"><div style="line-height:25px"> 另外,注意后提交的任务可能比前提交的任务先完成</div> </wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
如大多数人所已知的那样,它只提供了一个run方法,该方法既不接受任何参数,也不返回任何值。
如果你需要从一个未完成的任务中返回一个值,你就必须在该接口之外使用一个方法去等待该任务完成时通报的某种消息。
例如,下面的示例就是你在这种情景下可能做的事情:
Runnablerunnable=...;
Threadt=newThread(runnable);
t.start();
<wbr style="line-height:25px">t.join()</wbr><wbr style="line-height:25px">;<br style="line-height:25px"> Stringvalue=someMethodtoGetSavedValue()<br style="line-height:25px"> 严格来说,上述代码并无错误,但现在可用不同的方法去做,这要感谢J2SE5.0引入的Callable接口。<br style="line-height:25px"> 不同于Runnable接口拥有run方法,<wbr style="line-height:25px"><span style="color:#ff00ff; line-height:25px">Callable</span><span style="color:#000080; line-height:25px">接口提供的是call方法,该方法可以返回一个Object对象,</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">或可返回任何一个在泛型化格式中定义了的特定类型的对象</span><wbr style="line-height:25px">。<br style="line-height:25px"> publicinterfaceCallable<V>{<br style="line-height:25px"> Vcall()throwsException;<br style="line-height:25px"> }<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#003366; line-height:25px">因为你不可能把</span><span style="color:#ff6600; line-height:25px">Callable</span><span style="color:#003366; line-height:25px">对象传到</span><span style="color:#ff9900; line-height:25px">Thread</span><span style="color:#003366; line-height:25px">对象去执行,你可换用</span><span style="color:#ff6600; line-height:25px">ExecutorService</span><span style="color:#003366; line-height:25px">对象去执行</span><span style="color:#ff00ff; line-height:25px">Callable</span><span style="color:#003366; line-height:25px">对象。<br style="line-height:25px"> 该服务接受Callable对象,并经由submit方法去执行它。</span><br style="line-height:25px"><span style="line-height:25px"></span><span style="color:#0000ff; line-height:25px"><T>Future<T>submit(</span><span style="color:#ff00ff; line-height:25px">Callable</span><span style="color:#0000ff; line-height:25px"><T>task)</span><wbr style="line-height:25px"><br style="line-height:25px"> 如该方法的定义所示,提交一个Callable对象给ExecutorService会返回一个Future对象。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">然后,Future的get方法将会阻塞,直到任务完成</span><wbr style="line-height:25px">。<br style="line-height:25px"> 为了证明这一点,下面的例子为命令行中的每个词都创建一个单独的Callable实例,然后把这些词的长度加起来。<br style="line-height:25px"> 各个Callable对象将只是计算它自己的词的长度之和。Futures对象的Set集合将被保存以便从中获得计算用的值。<br style="line-height:25px"> 如果需要保持返回值的顺序,则可换用一个List对象。<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.*;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.concurrent.*;</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicclass</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">CallableExample</span><span style="color:#3366ff; line-height:25px">{<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">publicstatic</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#ff9900; line-height:25px">WordLengthCallable</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">implementsCallable{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">privateStringword;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">WordLengthCallable(Stringword){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.word=word;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#808000; line-height:25px">Integer</span><span style="color:#3366ff; line-height:25px">call(){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#99cc00; line-height:25px">Integer</span><span style="color:#3366ff; line-height:25px">.valueOf(word.length());</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">main</span><span style="color:#3366ff; line-height:25px">(Stringargs[])throwsException{</span><br style="line-height:25px"><span style="color:#0000ff; line-height:25px">ExecutorServicepool=Executors.newFixedThreadPool(3);<br style="line-height:25px"> Set<Future<Integer>>set=newHashSet<Future<Integer>>();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">for</span><span style="color:#3366ff; line-height:25px">(Stringword:args){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Callable<Integer>callable=newWordLengthCallable(word);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Future<Integer>future=pool.submit(callable);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(future);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intsum=0;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">for(Future<Integer>future:set){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">sum+=future.get();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">system.out.printf("Thesumoflengthsis%s%n",sum);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">system.exit(sum);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> WordLengthCallable保存了每个词并使用该词的长度作为call方法的返回值。<br style="line-height:25px"> 这个值可能会花点儿时间去生成,不过在这个例子中,可以立即知道它。call方法的唯一要求是这个值要在call方法的结尾处返回。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">当Future的get方法稍后被调用时,如果任务运行得很快的话,Future将会立刻得到这个值(如同本例的情况),否则将一直等到该值生成完毕为止<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"> 对Future的get方法的调用会阻塞当前线程并等待任务结束,而不会阻塞其它的任务和线程。<br style="line-height:25px"> 这个特定的例子使用固定数线程池来产生ExecutorService对象,但其它有效的方法也是可行的。<br style="line-height:25px"><div style="line-height:25px"> 另外,注意后提交的任务可能比前提交的任务先完成</div> </wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>