У меня есть основной вопрос о том, как ExecutorService
работает на Java.ExecutorService vs Casual Thread Spawner
Сложно видеть разницу между просто созданием 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, не могли бы вы рассказать мне разницу между этими двумя и в каких случаях следует использовать конкретную, а не другую?
Использование ИСПОЛНИТЕЛЬ службы: Счетчик (задачи)
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»? –