Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Когда метод main создает объекты-потоки Thread, он не сохраняет на них ссылки. Обычный объект, «забытый» таким образом, стал бы легкой добычей сборщика мусора, но только не объект-поток Thread. Каждый поток (Thread) самостоятельно «регистрирует» себя, то есть на самом деле ссылка на него где-то существует, и сборщик мусора не вправе удалить его объект.

Исполнители

Исполнители (executors), появившиеся в библиотеке java.util.concurrent в Java SE5, упрощают многозадачное программирование за счет автоматизации управления объектами Thread. Они создают

дополнительную логическую прослойку между клиентом и выполнением задачи; задача выполняется не напрямую клиентом, а промежуточным объектом. Исполнители позволяют управлять выполнением асинхронных задач без явного управления жизненным циклом потоков. Именно такой способ запуска задач рекомендуется использовать в Java SE5/6.

Вместо явного создания объектов Thread в MoreBasicThreads.java мы можем воспользоваться исполнителем. Объект LiftOff умеет выполнять определенную операцию и предоставляет единственный метод для выполнения. Объект Execu-torService умеет создавать необходимый контекст для выполнения объектов Runnable. В следующем примере класс CachedThreadPool создает один поток для каждой задачи. Обратите внимание: объект ExecutorService создается статическим методом класса Executors, определяющим разновидность исполнителя:

// concurrency/CachedThreadPool java

import java util concurrent *.

public class CachedThreadPool {

public static void main(String[] args) {

ExecutorService exec = Executors.newCachedThreadPoolО, for(int i = 0, i < 5; i++)

exec execute(new LiftOffO); exec shutdownО.

}

} /* Output (Пример)

#0(9). #0(8). #1(9). #2(9). #3(9). #4(9). #0(7). #1(8). #2(8). #3(8). #4(8). #0(6).

#1(7). #2(7). #3(7). #4(7). #0(5). #1(6). #2(6). #3(6). #4(6), #0(4). #1(5). #2(5).

#3(5). #4(5). #0(3). #1(4). #2(4). #3(4). #4(4). #0(2). #1(3). #2(3). #3(3). #4(3).

#0(1). #1(2). #2(2). #3(2). #4(2). #0(Liftoff!). #1(1). #2(1). #3(1). #4(1).

#1(Liftoff!). #2(Liftoff1). #3(Liftoff!). #4(Liftoff!).

*/// ~

Очень часто для создания и управления всеми задачами в системе достаточно одного исполнителя.

Вызов shutdown предотвращает передачу Executor новых задач. Текущий поток (в данном случае тот, в котором выполняется main) продолжает выполняться со всеми задачами, переданными до вызова shutdown. Работа программы прекращается после завершения всех задач в Executor.

CachedThreadPool в этом примере легко заменяется другим типом Executor. Например, в потоковом пуле фиксированного размера (FixedThreadPool) используется ограниченный набор потоков для выполнения переданных задач:

// concurrency/FixedThreadPool.java

import java.util.concurrent *.

public class FixedThreadPool {

public static void main(String[] args) {

// В аргументе конструктора передается количество потоков ExecutorService exec = Executors newFixedThreadPool(5);

for(int i = 0; i < 5; i++)

exec, execute (new LiftOffO); exec.shutdownO;

}

} /* Output: (Sample)

#0(9). #0(8). #1(9). #2(9). #3(9). #4(9). #0(7). #1(8). #2(8). #3(8). #4(8). #0(6).

#1(7). #2(7). #3(7). #4(7). #0(5). #1(6). #2(6). #3(6). #4(6). #0(4). #1(5). #2(5).

#3(5). #4(5). #0(3). #1(4). #2(4). #3(4). #4(4). #0(2). #1(3). #2(3). #3(3). #4(3).

#0(1). #1(2). #2(2). #3(2). #4(2). #0(Liftoff!), #1(1). #2(1). #3(1). #4(1).

#1(Liftoff!). #2(Liftoff!). #3(Liftoff!). #4(Liftoff!).

*///:-

С FixedThreadPool

дорогостоящая операция создания потоков выполняется только один раз, в самом начале, поэтому количество потоков остается фиксированным. Это способствует экономии времени, поскольку вам не приходится нести затраты, связанные с созданием потока, для каждой отдельной задачи. В системах, управляемых событиями, обеспечивается максимальная скорость выполнения обработчиков событий, так как они могут просто получить поток из пула. Перерасход ресурсов в такой схеме исключен, так как
FixedThreadPool использует ограниченное количество объектов Thread.

Исполнитель SingleThreadExecutor представляет собой аналог FixedThreadPool с одним потоком. Например, он может быть полезен для выполнения долгосрочных операций (скажем, прослушивания входящих подключений по сокету) и для коротких операций, выполняемых в отдельных потоках, — скажем, обновления локальных или удаленных журналов.

Если SingleThreadExecutor передается более одной задачи, эти задачи ставятся в очередь, и каждая из них отрабатывает до завершения перед началом следующей задачи, причем все они используют один и тот же поток. В следующем примере мы видим, что задачи последовательно завершаются в порядке их поступления. Таким образом, SingleThreadExecutor организует последовательное выполнение поступающих задач и поддерживает свою (внутреннюю) очередь незавершенных задач.

//: concurrency/SingleThreadExecutor.java

import java.util.concurrent.*;

public class SingleThreadExecutor {

public static void main(String[] args) { ExecutorService exec =

Executors.newSi ngleThreadExecutor; for(int i = 0; i < 5; i++)

exec, execute (new LiftOffO); exec.shutdownO;

}

} /* Output:

#0(9). #0(8). #0(7). #0(6). #0(5). #0(4). #0(3). #0(2). #0(1). #0(L1ftoff!). #1(9).

#1(8). #1(7). #1(6). #1(5). #1(4). #1(3). #1(2). #1(1). #1(Liftoff!). #2(9). #2(8).

#2(7). #2(6). #2(5). #2(4). #2(3). #2(2). #2(1). #2<Liftoff!). #3(9). #3(8). #3(7).

#3(6), #3(5). #3(4). #3(3). #3(2). #3(1). «(Liftoff!). #4(9). #4(8). #4(7). #4(6).

#4(5). #4(4). #4(3). #4(2). #4(1). #4(Liftoff!).

Другой пример: допустим, имеется группа потоков, выполняющих операции с использованием файловой системы. Вы можете запустить эти задачи под управлением SingleThreadExecutor, чтобы в любой момент гарантированно выполнялось не более одной задачи. При таком подходе вам не придется возиться с синхронизацией доступа к общим ресурсам (без риска для целостности файловой системы). Возможно, в окончательной версии кода будет правильнее синхронизировать доступ к ресурсу (см. далее в этой главе), но SingleThreadExecutor позволит быстро организовать координацию доступа при построении рабочего прототипа.

Поделиться:
Популярные книги

Зодчий. Книга V

Погуляй Юрий Александрович
5. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга V

Брак по-драконьи

Ардова Алиса
Фантастика:
фэнтези
8.60
рейтинг книги
Брак по-драконьи

Викинг

Мазин Александр Владимирович
1. Викинг
Приключения:
исторические приключения
8.92
рейтинг книги
Викинг

Тихие ночи

Владимиров Денис
2. Глэрд
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Тихие ночи

Мастер Трав III

Мордорский Ваня
3. Мастер Трав
Фантастика:
фэнтези
рпг
фантастика: прочее
попаданцы
5.75
рейтинг книги
Мастер Трав III

Третье правило диверсанта

Бычков Михаил Владимирович
Фантастика:
постапокалипсис
5.67
рейтинг книги
Третье правило диверсанта

Товарищ «Чума» 8

lanpirot
8. Товарищ "Чума"
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Товарищ «Чума» 8

Кодекс Охотника. Книга XV

Винокуров Юрий
15. Кодекс Охотника
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XV

Волкодав

Семёнова Мария Васильевна
1. Волкодав
Фантастика:
фэнтези
героическая фантастика
9.46
рейтинг книги
Волкодав

Технарь

Муравьёв Константин Николаевич
1. Технарь
Фантастика:
космическая фантастика
попаданцы
7.13
рейтинг книги
Технарь

Черный Маг Императора 19

Герда Александр
19. Черный маг императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 19

Геном хищника. Книга шестая

Гарцевич Евгений Александрович
6. Я - Легенда!
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Геном хищника. Книга шестая

Эпоха Опустошителя. Том V

Павлов Вел
5. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том V

Цеховик. Книга 1. Отрицание

Ромов Дмитрий
1. Цеховик
Фантастика:
попаданцы
альтернативная история
5.75
рейтинг книги
Цеховик. Книга 1. Отрицание