我有一个关于Java中ExecutorService
的基本问题。
很难看出简单地创建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接口。您能告诉我两者之间的区别,以及在哪些情况下应该使用特定的方法而不是另一个吗?
使用Executor Service:计数器(任务)
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
而不是创建新的线程,因此我不确定您在这种情况下要比较什么。您是否困惑于何时使用Runnable
和何时使用Callable
? - Dioxin