Существует пять способов асинхронного выполнения задач с использованием интерфейса ExecutorService, предоставляемого Java 6.
ExecutorService execService = Executors.newCachedThreadPool ();
Этот метод подхода создает пул потоков, который создает новые потоки по мере необходимости, но будет повторно использовать ранее созданные потоки, когда они станут доступны. Эти пулы обычно улучшают производительность программ, которые выполняют много кратковременных асинхронных задач. Если существующий поток недоступен, новый поток будет создан и добавлен в пул. Потоки, которые не использовались в течение 60 секунд, прекращаются и удаляются из кэша.
ExecutorService execService = Executors.newFixedThreadPool (10);
Этот метод подхода создает пул потоков, который повторно использует фиксированное количество потоков. Созданные nThreads будут активны во время выполнения. Если дополнительные задачи отправляются, когда все потоки активны, они будут ждать в очереди, пока поток не станет доступным.
ExecutorService execService = Executors.newSingleThreadExecutor ();
Этот метод подхода создает Исполнителя, который использует один рабочий поток, работающий из неограниченной очереди. Задачи гарантированно выполняются последовательно, и в любой момент времени будет активным не более одной задачи.
Методы ExecutorService:
execute (Runnable): выполняет данную команду в будущем.
submit (Runnable): метод submit возвращает Future Object, который представляет выполненную задачу. Future Object возвращает null, если задача выполнена правильно.
shutdown (): инициирует упорядоченное завершение работы, при котором выполняются ранее отправленные задачи, но новые задачи не принимаются. Вызов не имеет никакого дополнительного эффекта, если он уже выключен.
shutdownNow (): Пытается остановить все активно выполняющиеся задачи, останавливает обработку ожидающих задач и возвращает список задач, ожидающих выполнения.
Нет никаких гарантий, кроме попыток изо всех сил прекратить обработку активно выполняемых задач. Например, типичные реализации будут отменены через Thread.interrupt, поэтому любая задача, которая не отвечает на прерывания, может никогда не завершиться.
Пример приложения ниже:
ШАГ 1: СОЗДАТЬ MAVEN ПРОЕКТ
Maven проект создается как показано ниже. (Его можно создать с помощью Maven или IDE Plug-in).
ШАГ 2: СОЗДАЙТЕ НОВУЮ ЗАДАЧУ
Новая задача создается путем реализации интерфейса Runnable (создания потока), как показано ниже. Класс TestTask определяет бизнес-логику, которая будет выполняться.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package com.otv.task; import org.apache.log4j.Logger; /** * @author onlinetechvision.com * @since 24 Sept 2011 * @version 1.0.0 * */ public class TestTask implements Runnable { private static Logger log = Logger.getLogger(TestTask. class ); private String taskName; public TestTask(String taskName) { this .taskName = taskName; } public void run() { try { log.debug( this .taskName + " is sleeping..." ); Thread.sleep( 3000 ); log.debug( this .taskName + " is running..." ); } catch (InterruptedException e) { e.printStackTrace(); } } public String getTaskName() { return taskName; } public void setTaskName(String taskName) { this .taskName = taskName; } } |
ШАГ 3: СОЗДАЙТЕ TestExecutorService с помощью newCachedThreadPool
TestExecutorService создается с использованием метода newCachedThreadPool. В этом случае количество созданных потоков указывается во время выполнения.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.otv; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.otv.task.TestTask; /** * @author onlinetechvision.com * @since 24 Sept 2011 * @version 1.0.0 * */ public class TestExecutorService { public static void main(String[] args) { ExecutorService execService = Executors.newCachedThreadPool(); execService.execute( new TestTask( "FirstTestTask" )); execService.execute( new TestTask( "SecondTestTask" )); execService.execute( new TestTask( "ThirdTestTask" )); execService.shutdown(); } } |
Когда TestExecutorService запущен, вывод будет выглядеть так:
1
2
3
4
5
6
|
24.09.2011 17:30:47 DEBUG (TestTask.java:21) - SecondTestTask is sleeping... 24.09.2011 17:30:47 DEBUG (TestTask.java:21) - ThirdTestTask is sleeping... 24.09.2011 17:30:47 DEBUG (TestTask.java:21) - FirstTestTask is sleeping... 24.09.2011 17:30:50 DEBUG (TestTask.java:23) - ThirdTestTask is running... 24.09.2011 17:30:50 DEBUG (TestTask.java:23) - FirstTestTask is running... 24.09.2011 17:30:50 DEBUG (TestTask.java:23) - SecondTestTask is running... |
ШАГ 4: СОЗДАЙТЕ TestExecutorService с помощью newFixedThreadPool
TestExecutorService создается с использованием метода newFixedThreadPool. В этом случае количество созданных потоков указывается во время выполнения.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.otv; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.otv.task.TestTask; /** * @author onlinetechvision.com * @since 24 Sept 2011 * @version 1.0.0 * */ public class TestExecutorService { public static void main(String[] args) { ExecutorService execService = Executors.newFixedThreadPool( 2 ); execService.execute( new TestTask( "FirstTestTask" )); execService.execute( new TestTask( "SecondTestTask" )); execService.execute( new TestTask( "ThirdTestTask" )); execService.shutdown(); } } |
Когда TestExecutorService запущен, ThirdTestTask выполняется после выполнения FirstTestTask и SecondTestTask. Результат будет виден как
ниже:
1
2
3
4
5
6
|
24.09.2011 17:33:38 DEBUG (TestTask.java:21) - FirstTestTask is sleeping... 24.09.2011 17:33:38 DEBUG (TestTask.java:21) - SecondTestTask is sleeping... 24.09.2011 17:33:41 DEBUG (TestTask.java:23) - FirstTestTask is running... 24.09.2011 17:33:41 DEBUG (TestTask.java:23) - SecondTestTask is running... 24.09.2011 17:33:41 DEBUG (TestTask.java:21) - ThirdTestTask is sleeping... 24.09.2011 17:33:44 DEBUG (TestTask.java:23) - ThirdTestTask is running... |
ШАГ 5: СОЗДАЙТЕ TestExecutorService с помощью newSingleThreadExecutor
TestExecutorService создается с использованием метода newSingleThreadExecutor. В этом случае создается только один поток, и задачи выполняются последовательно.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.otv; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.otv.task.TestTask; /** * @author onlinetechvision.com * @since 24 Sept 2011 * @version 1.0.0 * */ public class TestExecutorService { public static void main(String[] args) { ExecutorService execService = Executors.newSingleThreadExecutor(); execService.execute( new TestTask( "FirstTestTask" )); execService.execute( new TestTask( "SecondTestTask" )); execService.execute( new TestTask( "ThirdTestTask" )); execService.shutdown(); } } |
Когда TestExecutorService запущен, SecondTestTask и ThirdTestTask выполняются после завершения выполнения FirstTestTask. Результат будет виден как показано ниже:
1
2
3
4
5
6
|
24.09.2011 17:38:21 DEBUG (TestTask.java:21) - FirstTestTask is sleeping... 24.09.2011 17:38:24 DEBUG (TestTask.java:23) - FirstTestTask is running... 24.09.2011 17:38:24 DEBUG (TestTask.java:21) - SecondTestTask is sleeping... 24.09.2011 17:38:27 DEBUG (TestTask.java:23) - SecondTestTask is running... 24.09.2011 17:38:27 DEBUG (TestTask.java:21) - ThirdTestTask is sleeping... 24.09.2011 17:38:30 DEBUG (TestTask.java:23) - ThirdTestTask is running... |
ШАГ 6: ССЫЛКИ
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
Ссылка: Java Executor Service Types от нашего партнера JCG Эрен Авсарогуллари в блоге Online Technology Vision