简体   繁体   English

callable 是否也在线程中执行?

[英]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()方法只是调用实例化时提供给ThreadRunnable实例上的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不会直接执行您提交的RunnableCallable实现。 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> .其中taskQueueBlockingQueue<Runnable>的实例。 When you submit a Runnable or Callable , they get put in this queue.当您提交RunnableCallable时,它们会被放入此队列中。 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()方法(如此处所示)执行Callablecall()方法。 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.

相关问题 为什么在子线程之后不执行父线程? - Why Parent thread does not gets executed after Child Thread? lock.notify() 是否仅在线程中的循环结束时执行 - Does lock.notify() gets executed only at the end of the loop in a thread 可调用语句尚未完成执行,但同一过程已完全执行 - Callable statement is not finishing its execution but the same procedure gets executed fully 一元运算符真的首先被执行吗? - Does the unary operator really gets executed first? Java中的多线程:只有一个线程被正确执行,其他线程被终止 - Multithreading in Java : Only one thread gets executed properly and other thread gets terminated 具有最高优先级的Java线程无法执行 - Java thread with the highest priority does not get executed 如果在线程的run函数中执行return语句,则线程在java中停止 - If return statement is executed in run function of a thread does the thread stop in java 如何确保if语句内的指令(也位于for循环内)仅执行一次? - How do I make sure the instruction inside an if statement, which is also inside a for loop, gets executed only once? 如果将回调两次分配给对象,事件是否会执行两次? - Does an event gets executed twice if callback was assigned twice to the object? JpaRepository 中用户指定的方法是否在单个事务中执行? - Does user specified methods in JpaRepository gets executed in single transaction?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM