- •Многопоточное программирование
- •Цели занятия
- •Понятие многопоточности
- •Реализация многопоточности
- •Реализация многопоточности
- •Особенности многопоточности
- •Использование класса Thread
- •Использование класса Thread
- •Использование класса Thread
- •Использование интерфейса
- •Использование интерфейса
- •Управление потоками
- •Нерекомендуемые действия над
- •Группы потоков
- •Группы потоков
- •Операции в группе потоков
- •Приоритеты потоков
- •Приоритеты потоков
- •Демон-потоки
- •Демон-группы потоков
- •Совместное использование
- •Совместное использование
- •Совместное использование
- •Совместное использование
- •Характерные ошибки
- •volatile
- •volatile
- •Специальные методы класса
- •Особенности использования
- •Прерывание потока
- •Пример
- •Пример
- •Пример
- •java.util.concurrent
- •java.util.concurrent
- •java.util.concurrent.locks
- •Lock Objects
- •ReentrantLock
- •Пример ReentrantLock
- •ReadWriteLock
- •Пример ReadWriteLock
- •Исполнители (Executors)
- •Интерфейсы исполнителей
- •Интерфейс Executor
- •Интерфейс
- •Thread Pools
- •Thread Pools
- •Executors
- •Пример ExecutorService
- •Пример ExecutorService.invokeAll()
- •InterruptedException
- •Прерывание потока
- •Пример InterruptedException
- •Пример восстановления статуса
- •Пример отменяемой задачи
- •Литература
Пример ExecutorService
51
Пример 5
class NetworkService implements Runnable { private final ServerSocket serverSocket; private final ExecutorService pool;
public NetworkService(int port, int poolSize) throws IOException { serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() { try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) { pool.shutdown(); }
}
}
class Handler implements Runnable { private final Socket socket;
Handler(Socket socket) { this.socket = socket; } public void run() { … }
}
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
Пример ExecutorService.invokeAll()
52
Пример 6
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() {
public String call() throws Exception { return "Task 1"; } });
callables.add(new Callable<String>() {
public String call() throws Exception { return "Task 2"; } });
callables.add(new Callable<String>() {
public String call() throws Exception { return "Task 3"; } });
List<Future<String>> futures = executorService.invokeAll(callables); for(Future<String> future : futures) {
System.out.println("future.get = " + future.get());
}
executorService.shutdown();
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
InterruptedException
53
• InterruptedException должен бросать любой метод, который может заблокировать поток и причиной блокировки является перевод потока в состояние WAITING или SLEEPING
• Помимо методов Object.wait(), Thread.sleep()
и Thread.join() есть ещё масса других, например, Lock.lockInterruptibly(), Condition.await(), Semaphore.aquire()
• Это исключение выбрасывается только в том случае, когда на объекте потока, который заблокирован вызовом такого метода, вызывается interrupt()
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
Прерывание потока
54
•Каждый поток имеет связанное с ним булево свойство, которое отображает его статус прерывания
•Статус прерывания изначально имеет значение false; когда поток прерывается каким- либо другим потоком путем вызова Thread.interrupt(), то происходит одно из двух:
Если другой поток выполняет прерываемый метод блокирования низкого уровня, то он разблокируется и выдает
InterruptedException
Иначе interrupt() просто устанавливает статус прерывания потока
•Код, действующий в прерванном потоке, может позднее обратиться к статусу прерывания, чтобы посмотреть, был ли запрос на прекращение выполняемого действия; статус прерывания может быть прочитан с помощью Thread.isInterrupted(),
иможет быть прочитан и сброшен за одну операцию при помощи неудачно названного
Thread.interrupted()
•Когда один поток прерывает другой, прерванный поток не обязательно немедленно прекратит делать то, что он делал, напротив, прерывание является вежливым способом, чтобы попросить другой поток прекратить то, что он делает, если он не против, когда ему это будет удобно
•Некоторые методы, например, Thread.sleep(), серьезно относятся к такой просьбе, но методы не обязаны обращать внимание на прерывание
•Неблокирующие методы, выполнение которых занимает много времени, могут положительно отнестись к просьбам о прерывании, путем опроса статуса прерывания,
ив случае прерывания вернуться к более раннему этапу
•Вы можете проигнорировать запрос о прерывании, но это может нанести ущерб ответной реакции
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
Пример InterruptedException
55
Пример 7
public class PlayerMatcher { private PlayerSource players;
public PlayerMatcher(PlayerSource players) { this.players = players; } public void matchPlayers() throws InterruptedException {
try {
Player playerOne, playerTwo; while (true) {
playerOne = playerTwo = null; playerOne = players.waitForPlayer(); playerTwo = players.waitForPlayer(); startNewGame(playerOne, playerTwo);
}
} catch (InterruptedException e) { if (playerOne != null)
players.addPlayer(playerOne); throw e;
}
}
}
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
Пример восстановления статуса
56
Пример 8
public class TaskRunner implements Runnable { private BlockingQueue<Task> queue;
public TaskRunner(BlockingQueue<Task> queue) { this.queue = queue;
}
public void run() { try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS); task.execute();
}
} catch (InterruptedException e) { Thread.currentThread().interrupt();
}
}
}
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
Пример отменяемой задачи
57
Пример 9
public class PrimeProducer extends Thread { private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) { this.queue = queue;
}
public void run() { try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) { /* Allow thread to exit */
}
}
public void cancel() { interrupt();
}
}
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
Литература
58• Арнольд Кен, Гослинг Джеймс, Холмс Дэвид. Язык программирования Java. 3-е изд.: Пер. с
англ. – М.: Издательский дом «Вильямс», 2001. –
624 с.: ил. ISBN 5-8459-0215-0 (рус.).
•Хорстманн Кей С., Корнелл Гари. Java 2. Библиотека профессионала, том 1. Основы. 8-е издание.: Пер. с англ. – М.: ООО «И.Д. Вильямс», 2008. – 816 с.: ил. ISBN 978-5-8459-1378-4 (рус.).
•Вязовик Н.А. Программирование на Java – М.: Интернет-Ун-т Информ. Технологий, 2003.
•http://docs.oracle.com/javase/tutorial/essential/con
currency/highlevel.html
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |
