import java.util.*;
public class Worker extends Thread {
public static void main(String[] args)
throws InterruptedException {
final Worker worker = new Worker();
worker.start();
Timer timer = new Timer(true);
timer.schedule(
new TimerTask() {
public void run() {
worker.keepWorking();
}
}, 500);
sleep(400);
worker.quit();
}
private volatile boolean stop = false;
public void run() {
while (!stop) pretendToWork();
System.out.println("Beer is good!");
}
private void pretendToWork() {
try {
sleep(300);
}
catch (InterruptedException exception) {
}
}
synchronized void keepWorking() {
stop = false;
}
synchronized void quit() {
stop = true;
join();
}
}
Беглый анализ показывает, что где-то через секунду программа напишет
Beer is good!
и завершит свою работу. Но на самом деле она зависает! Проблема в том, что внутренняя реализация метода join
вызывает метод wait
на экземпляре класса Thread
, который должен быть присоединён. А вызов метода wait
снимает блокировку!Фундаментальная причина ошибочного поведения класса
Worker
- использование блокировки по экземпляру (synchronized
методы). Не полагайтесь на поведение библиотеки - делайте собственные объекты блокировки, которые не доступны никому другому. Это напоминает раздел 15 книги Эффективное программирование Джошуа Блоха.
Комментариев нет:
Отправить комментарий