在哪里使用可调用以及在哪里使用Runnable接口?

Gee*_*arn 7 java callable runnable

我是Java的新手,我正在阅读多线程的概念,在进行多线程的各种实现时,我经历了这两个概念.这在Java问题中Runnable和Callable接口之间的区别指出了两者之间的区别以及使用的位置.

我怀疑Callable是否能够完成Runnable的所有功能,为什么这么多人使用Runnable而不是可调用?与Runnable Inteface相比,实现Callable接口是否有额外的开销?

GPI*_*GPI 6

java.util.concurrent发布Java 5版本的软件包之前,没有其他选项可以进行并发计算,而是直接操作Threads.

您可以直接操作线程,例如通过子类化:

public class MyThread extends Thread {
    public void run() {
        myComputation();
    }
}
Run Code Online (Sandbox Code Playgroud)

或者你可以通过创建一个Runnable优先的方式来做同样的事情(主要是因为你不需要子类化任何东西,这提供了明确的关注点分离,更好的代码重用或通常更好的组合):

public class MyRunnable implements Runnable {
    public void run() {
        mycomputation();
    }
}
new Thread(new MyRunnable()).start();
Run Code Online (Sandbox Code Playgroud)

但无论您使用哪种方式,都必须创建,启动,操作,加入线程.哪个有缺点:你可以创建多少个线程?这个贵吗?(在某些时候,它是,尽管每个JVM实现变得更便宜和更便宜.)

此外,这个API本身也有开发人员必须克服的限制:如果我想从a返回一个值Runnable,看到签名不允许它怎么办?我怎么知道我的Runnable失败了Exception?有一些事情,例如异常处理程序等允许使用线程,但它是一个安静的重复,容易出错的任务.

进入java.util.concurrent包裹!它提供了所有这些(以及更多)的答案!

您想要为多个"工作单元"重复使用线程(不管是Runnable不是?):您可以.想知道"工作单位"是否完成或失败:你可以.想要返回一个值:你可以.想要将某些任务动态优先于其他任务吗?当然.需要能够安排任务吗?可以做.等等.

Runnables 替换你的Callables(这很简单,两者都是单一方法接口!),停止操纵Threads以支持Futures并离开管道ExecutorService.

我怀疑Callable是否能够完成Runnable的所有功能,为什么这么多人使用Runnable而不是可调用?

也许他们确实有旧代码(Java 1.4?).也许他们不了解更高级别抽象的好处,而更喜欢低级别的Thread东西?

一般来说,Thread自从并发API出现以来,绝对没有理由更喜欢使用s.

与Runnable接口相比,实现Callable接口是否有额外的开销?

在"实施Callable"vs中Runnable,没有没有.但是这些新Callable东西需要付出代价,因为在内部,它们都会回归到Threads和Runnables(至少,当前的实现会这样做).但是你可能实际上获得了性能,因为新的功能就像线程重用更容易!

所以,是的,并发API有它的成本,但它在任何标准用例中绝对,完全可以忽略不计,但它也有新的优势,使它在许多方面变得更好,包括性能.

此外,您已经从API中获得了大量新的可能性(参见Fork/Join框架,请参阅Java 8中的并行流,...),并减少对"自定义","自制"的任何扭结的需求"所述功能的并发代码,众所周知很难做到.

利益/成本比完全支持"新"并发API.