gpt4 book ai didi

java - ExecutorService vs Casual Thread Spawner

转载 作者:IT老高 更新时间:2023-10-28 20:46:27 24 4
gpt4 key购买 nike

我有一个关于 ExecutorService 如何在 Java 中工作的基本问题。

很难看出简单地创建 Threads 以并行执行某些任务和将每个任务分配给 ThreadPool 之间的区别。

ExecutorService 看起来也非常简单高效,所以我想知道为什么我们不一直使用它。

这只是一种方式比另一种更快地执行其工作的问题吗?

这里有两个非常简单的例子来说明这两种方式之间的区别:

使用执行器服务:Hello World(任务)

static class HelloTask implements Runnable {
String msg;

public HelloTask(String msg) {
this.msg = msg;
}
public void run() {
long id = Thread.currentThread().getId();
System.out.println(msg + " from thread:" + id);
}
}

使用执行器服务:Hello World(创建执行器,提交)

static class HelloTask {
public static void main(String[] args) {
int ntasks = 1000;
ExecutorService exs = Executors.newFixedThreadPool(4);

for (int i=0; i<ntasks; i++) {
HelloTask t = new HelloTask("Hello from task " + i);
exs.submit(t);
}
exs.shutdown();
}
}

下面显示了一个类似的例子,但是扩展了 Callable 接口(interface),你能告诉我两者之间的区别,在什么情况下应该使用特定的而不是另一个?

使用执行器服务:计数器(任务)

static class HelloTaskRet implements Callable<Long> {
String msg;

public HelloTaskRet(String msg) {
this.msg = msg; }

public Long call() {
long tid = Thread.currentThread().getId();
System.out.println(msg + " from thread:" + tid);
return tid;
}
}

使用执行器服务:(创建、提交)

static class HelloTaskRet {
public static void main(String[] args) {
int ntasks = 1000;
ExecutorService exs = Executors.newFixedThreadPool(4);

Future<Long>[] futures = (Future<Long>[]) new Future[ntasks];

for (int i=0; i<ntasks; i++) {
HelloTaskRet t = new HelloTaskRet("Hello from task " + i);
futures[i] = exs.submit(t);
}
exs.shutdown();
}
}

最佳答案

虽然问题和示例代码不相关,但我会尝试澄清两者。ExecutorService 相对于随意生成线程的优势在于它的行为是可预测的,并且避免了线程创建的开销,这在 JVM 上相对较大(例如,它需要为每个线程保留内存)。通过可预测性,至少对于 fixedThreadPool,我的意思是您知道并发线程的最大数量,并且您知道它们何时以及如何创建(因此您的 JVM 不会在突然发生时崩溃峰)。

By Vince Emigh: ExecutorService also supports cachedThreadPool, which doesn't have a max. The main reason people choose to use ExecutorService is to prevent the overhead of creating multiple threads (by using worker threads). It's mostly used in cases where many small tasks need to be executed on a separate thread. Also, don't forget about singleThreadExecutor.

现在,关于 RunnableCallable 的话题,从您的示例中很容易看出。 Callables 可以返回一个值占位符 (Future),该占位符最终将在未来由实际值填充。 Runnables 不能返回任何东西。

By Vince Emigh: Runnable also cannot throw exceptions, while Callable can.

关于java - ExecutorService vs Casual Thread Spawner,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26938210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com