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

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

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Возврат значений из задач

Интерфейс Runnable представляет отдельную задачу, которая выполняет некоторую работу, но не возвращает значения. Если вы хотите, чтобы задача возвращала значение, реализуйте интерфейс Callable вместо интерфейса Runnable. Параметризованный интерфейс Callable, появившийся в Java SE5, имеет параметр типа, представляющий возвращаемое значение метода call (вместо run), а для его вызова должен использоваться метод ExecutorService submit. Простой пример:

//. concurrency/Cal1ableDemo.java

import java.util concurrent.*;

import java.util.*,

class TaskWithResult implements Callable<String> {

private int id;

public TaskWithResult(int id) { this id = id.

}

public String call О {

return "результат TaskWithResult " + id;

}

}

public class CallableDemo {

public static void main(String[] args) {

ExecutorService exec = Executors.newCachedThreadPoolО; ArrayList<Future<String>> results =

new ArrayList<Future<String». for(int i = 0; i < 10; i++)

results.add(exec submit(new TaskWithResult(i))); for(Future<String> fs ; results) try {

// Вызов get О блокируется до завершения; System.out.pri nt1n(fs.get); } catch(InterruptedException e) { System.out.println(e). return;

} catch(ExecutionException e) { System out println(e); } finally {

exec.shutdown;

}

} /* Output•

результат TaskWithResult О результат TaskWithResult 1 результат TaskWithResult 2 результат TaskWithResult 3 результат TaskWithResult 4 результат TaskWithResult 5 результат TaskWithResult 6 результат TaskWithResult 7 результат TaskWithResult 8 результат TaskWithResult 9 *///:-

Метод submit создает объект Future, параметризованный по типу результата, возвращаемому Callable. Вы можете обратиться к Future с запросом isDone, чтобы узнать, завершена ли операция. После завершения задачи и появления результата производится его выборка методом get. Если get вызывается без предварительной проверки isDone, вызов блокируется до появления результата. Также можно вызвать get с интервалом тайм-аута.

Перегруженный метод Executors.callable получает Runnable и выдает Callable. ExecutorService содержит методы для выполнения коллекций объектов Callable.

Ожидание

Другим способом управления вашими потоками является вызов метода sleep, который переводит поток в состояние ожидания на заданное количество миллисекунд. Если в классе LiftOff заменить вызов yield на вызов метода sleep, будет получен следующий результат:

//: concurrency/SleepingTask.java // Вызов sleepO для приостановки потока, import java.util.concurrent.*;

public class SIeepingTask extends LiftOff { public void run { try {

while(countDown-- > 0) {

System.out.pri nt(status);

// Старый стиль.

// Thread.sleep(lOO);

// Стиль Java SE5/6:

TimeUnit MILLISECONDS.sieep(100);

}

} catchdnterruptedException e) {

System.err.pri ntin("Interrupted");

}

}

public static void main(String[] args) {

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

exec.execute(new SIeepi ngTask); exec.shutdownO;

}

#0(9). #1(9)

#2(7). #3(7)

#4(5). #0(4)

#1(2). #2(2)

#1(Liftoff") */// _ #2(9). #3(9) #4(7). #0(6) #1(4). #2(4) #3(2). #4(2) #2(Liftoff!) #4(9). #0(8) #1(6). #2(6) #3(4). #4(4) #0(1). #1(1) #3(Liftoff!) #1(8). #2(8) #3(6). #4(6) #0(3). #1(3) #2(1). #3(1) #4(Liftoff!)

#3(8). #4(8). #0(7). #1(7).

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

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

#4(1). #0(Liftoff1).

Вызов метода sleep может привести к исключению InterruptedException; перехват этого исключения продемонстрирован в run. Поскольку исключения не распространяются по потокам обратно в main, вы должны локально обработать любые исключения, возникающие внутри задачи.

В Java SE5 появилась новая версия sleep, оформленная в виде метода класса Timellnit; она продемонстрирована в приведенном примере. Она делает программу более наглядной, поскольку вы можете указать единицы измерения продолжительности задержки. Класс Timellnit также может использоваться для выполнения преобразований, как будет показано далее в этой главе.

На некоторых платформах задачи выполняются в порядке «идеального распределения» — от 0 до 4, затем снова от 4 до 0. Это вполне логично, поскольку после каждой команды вывода задача переходит в состояние ожидания, что позволяет планировщику потоков переключиться на другой поток. Тем не менее такое поведение зависит от базовой реализации потокового механизма, поэтому полагаться на него нельзя. Если вам потребуется управлять порядком выполнения задач, используйте средства синхронизации (см. далее) или же вообще откажитесь от использования потоков и напишите собственные функции синхронизации, которые передают управление друг другу в нужном порядке.

Приоритет

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

В подавляющем большинстве случаев все потоки должны выполняться со стандартным приоритетом. Любые попытки манипуляций с приоритетами обычно являются ошибкой.

Следующий пример демонстрирует использование приоритетов. Приоритет существующего потока читается методом getPriority и задается методом setPriority:

//• concurrency/Si mplePri ori ti es.java

// Использование приоритетов потоков.

import java.util.concurrent.*.

public class SimplePriorities implements Runnable { private int countDown = 5;

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

Черный рынок

Вайс Александр
6. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Черный рынок

Мечник Вернувшийся 1000 лет спустя

Ткачев Андрей Юрьевич
1. Вернувшийся мечник
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Мечник Вернувшийся 1000 лет спустя

Газлайтер. Том 19

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

#Бояръ-Аниме. Газлайтер. Том 37

Володин Григорий Григорьевич
37. История Телепата
Фантастика:
фэнтези
аниме
боевая фантастика
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 37

Тринадцатый XIII

NikL
13. Видящий смерть
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Тринадцатый XIII

Сын счастья

Вассму Хербьёрг
2. Книга Дины
Проза:
современная проза
5.00
рейтинг книги
Сын счастья

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

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

Газлайтер. Том 26

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

Двойник короля 16

Скабер Артемий
16. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 16

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Пушкарь. Пенталогия

Корчевский Юрий Григорьевич
Фантастика:
альтернативная история
8.11
рейтинг книги
Пушкарь. Пенталогия

Элизиум. Аликс и монеты

Андерсон Александр
1. Элизиум
Фантастика:
фэнтези
сказочная фантастика
8.98
рейтинг книги
Элизиум. Аликс и монеты

Рассвет русского царства 3

Грехов Тимофей
3. Новая Русь
Фантастика:
историческое фэнтези
альтернативная история
5.00
рейтинг книги
Рассвет русского царства 3

Изгои

Владимиров Денис
5. Глэрд
Фантастика:
фэнтези
боевая фантастика
5.00
рейтинг книги
Изгои