[英]Does callable also gets executed in a thread?
When we pass a runnabble to an executorService like当我们将 runnabble 传递给 executorService 时
Future future = executorService.submit(runnable);未来 future = executorService.submit(runnable);
// As here executorService maps the object into instance of // 这里 executorService 将 object 映射到实例
new FutureTask(runnable);新的 FutureTask(可运行); and after that it executes the runnable using addWorker(runnable) -> which internally uses thread for execution.
然后它使用 addWorker(runnable) -> 执行 runnable,它在内部使用线程执行。
As talking about callable正如谈论可调用
Future future = executorService.submit(callable);未来 future = executorService.submit(callable); // As here executorService maps the object into instance of
// 这里 executorService 将 object 映射到实例
new FutureTask(callable);新的 FutureTask(可调用);
How does JVM maps the callable and make it run concurrently. JVM 如何映射可调用对象并使其并发运行。 How does it uses the Thread to execute callable and maps the return result of the callable method in FutureTask instance.
它是如何使用Thread执行callable并将callable方法的返回结果映射到FutureTask实例中的。
because Thread has a very tight contract with run() method, How does JVM manages to call the call() method of callable if it uses a Thread to execute the callable.因为 Thread 与 run() 方法有非常紧密的联系,如果 JVM 使用 Thread 来执行可调用对象,它如何设法调用可调用对象的 call() 方法。
Yes, the Callable
gets executed by whichever thread grabs the task.是的,
Callable
由获取任务的线程执行。
I think you're giving Runnable
too much importance.我认为您对
Runnable
的重视程度过高。 The Thread
class does implement Runnable
, but that is not what makes the code multithreaded. Thread
class 确实实现了Runnable
,但这并不是使代码成为多线程的原因。 That comes from Java starting an OS-level thread when you call the Thread#start()
method (ignoring virtual threads ).当您调用
Thread#start()
方法(忽略虚拟线程)时,它来自 Java 启动操作系统级线程。 After starting the thread, that new thread then calls the Thread#run()
method.启动线程后,新线程会调用
Thread#run()
方法。 Any code that gets executed as a consequence of that run()
method being executed is executed on said new thread (ignoring communication between threads).由于执行
run()
方法而执行的任何代码都在所述新线程上执行(忽略线程之间的通信)。
By default, the Thread#run()
method simply calls the Runnable#run()
method on the Runnable
instance given to the Thread
when it was instantiated.默认情况下,
Thread#run()
方法只是调用实例化时提供给Thread
的Runnable
实例上的Runnable#run()
方法。
Now, you seem to be talking about ThreadPoolExecutor
.现在,您似乎在谈论
ThreadPoolExecutor
。 Note that is only one implementation of ExecutorService
, but I will focus on it, too.请注意,这只是
ExecutorService
的一种实现,但我也会关注它。 Internally, ThreadPoolExecutor
creates one or more Thread
instances and starts them when and as appropriate.在内部,
ThreadPoolExecutor
创建一个或多个Thread
实例并在适当的时候启动它们。 These Thread
s do not execute your submitted Runnable
or Callable
implementations directly.这些
Thread
不会直接执行您提交的Runnable
或Callable
实现。 Instead, each Thread
is created with an internal implementation of Runnable
: Worker
.相反,每个
Thread
都是使用Runnable
: Worker
的内部实现创建的。
Vastly simplified, this worker essentially does the following:大大简化后,该 worker 基本上执行以下操作:
while (!shutdown) {
Runnable task = taskQueue.take();
task.run();
}
Where taskQueue
is an instance of BlockingQueue<Runnable>
.其中
taskQueue
是BlockingQueue<Runnable>
的实例。 When you submit a Runnable
or Callable
, they get put in this queue.当您提交
Runnable
或Callable
时,它们会被放入此队列中。 This is how tasks are submitted by one thread but executed by another.这就是任务由一个线程提交但由另一个线程执行的方式。
However, the Runnable
or Callable
you submit is not put in the queue directly .但是你提交的
Runnable
或者Callable
并没有直接放到队列中。 First it wraps your object in another that understands how to communicate a result back.首先,它将您的 object 包装在另一个了解如何返回结果的系统中。 In other words, an implementation of
Future
.换句话说,是
Future
的实现。 But this Future
still needs to also be a Runnable
, which is where the RunnableFuture
interface comes from.但是这个
Future
仍然需要也是一个Runnable
,这是RunnableFuture
接口的来源。 The implementation of this interface that is used by ThreadPoolExecutor
is FutureTask
, at least by default (you can override certain methods to return your own implementation). ThreadPoolExecutor
使用的这个接口的实现是FutureTask
,至少在默认情况下是这样(您可以覆盖某些方法以返回您自己的实现)。 So, by default, it is a FutureTask
that wraps your object that is actually put into the queue.因此,默认情况下,它是一个
FutureTask
,它包装了实际放入队列的 object。
The FutureTask
class internally wraps any Runnable
in a Callable
. FutureTask
class 在内部将任何Runnable
包装在Callable
中。 Again simplified, it essentially does:再次简化,它本质上是:
// just the constructors
public FutureTask(Callable<V> callable) {
this.callable = callable;
}
public FutureTask(Runnable r, V result) {
this.callable = () -> {
r.run();
return result;
};
}
Note: If you do executorService.submit(runnable)
then result
will ultimately be null
.注意:如果你执行
executorService.submit(runnable)
那么result
最终将是null
。
Then the FutureTask#run()
method (as seen here ) executes the call()
method of the Callable
.然后
FutureTask#run()
方法(如此处所示)执行Callable
的call()
方法。 Once again vastly simplified, it essentially does:再次大大简化,它本质上是:
@Override
public void run() {
try {
this.result = this.callable.call();
} catch (Exception ex) {
this.error = ex;
}
}
Note: This ignores the relatively complex code needed to synchronize the state of the task between threads, so that eg, calls to get()
wait for the result as needed (whether a return value or an exception).注意:这忽略了在线程之间同步任务的 state 所需的相对复杂的代码,因此,例如,调用
get()
根据需要等待结果(无论是返回值还是异常)。 If you're interested in that, take a look at the implementation linked above.如果您对此感兴趣,请查看上面链接的实现。
Given the FutureTask#run()
method is executed by whatever thread grabbed it from the task queue, the Callable
will be executed by said thread.鉴于
FutureTask#run()
方法由从任务队列中获取它的任何线程执行, Callable
将由所述线程执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.