public class Solution {
public static void main(String[] args) throws InterruptedException {
OnlineGame onlineGame = new OnlineGame();
onlineGame.start();
}
public static class OnlineGame extends Thread {
public static volatile boolean isWinnerFound = false;
public static List<String> steps = new ArrayList<String>();
static {
steps.add("Начало игры");
steps.add("Сбор ресурсов");
steps.add("Рост экономики");
steps.add("Убийство врагов");
}
protected Gamer gamer1 = new Gamer("Ivanov", 3);
protected Gamer gamer2 = new Gamer("Petrov", 1);
protected Gamer gamer3 = new Gamer("Sidorov", 5);
public void run() {
gamer1.start();
gamer2.start();
gamer3.start();
while (!isWinnerFound) {
}
gamer1.interrupt();
gamer2.interrupt();
gamer3.interrupt();
}
}
public static class Gamer extends Thread {
private int rating;
public Gamer(String name, int rating) {
super(name);
this.rating = rating;
}
@Override
public void run() {
int i = 0;
try {
while (i < OnlineGame.steps.size()) {
System.out.println(getName() + ":" + OnlineGame.steps.get(i));
i++;
Thread.sleep(1000 / rating);
}
if (!OnlineGame.isWinnerFound) {
OnlineGame.isWinnerFound = true;
System.out.println(getName() + ":победитель!");
}
} catch (InterruptedException e) {
System.out.println(getName() + ":проиграл");
}
}
}
}
В методе run() класса Gamer после установки значения OnlineGame.isWinnerFound = true поток класса OnlineGame выходит из бесконечного цикла и завершает все три потока в классе Gamer. Как я могу быть уверен в том, что поток-"победитель" успеет завершиться прежде, чем будет прерван из класса OnlineGame?
Пытался как-то обойти этот нюанс, в итоге посмотрел решение и увидел, что по этому поводу никто не заморачивается.Anonymous #3104609
1 уровень
Как я могу быть уверен в том, что поток-"победитель" успеет завершиться прежде, чем будет прерван из класса OnlineGame?
Обсуждается
Комментарии (2)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
ГоффMaster
2 октября 2022, 18:21
Если это код из правильного решения, то он в некоторых случаях будет неправильно работать, видимо, валидатор эти случаи просто не проверяет.
Эту задачу интересно погонять много раз, задав игрокам одинаковые значения, что бы они практически одновременно заканчивали. Вот при такой толкотне на финише и всплывут некоторые поучительные моменты.
К твоему вопросу - это не важно, успеет поток-победитель завершится до того, как в OnlineGame ему кинут interrupt. interrupt вызывает исключение, пока поток спит, если поток в данный момент не спит, то он продолжит выполняться. А поток-победитель гарантированно не спит, когда меняет значение isWinnerFound на true, то есть поток-победитель в любом случае завершится сам, а interrupt будет им проигнорирован.
Изредка в тестах с одинаковыми игроками так и происходит - сообщение "проиграл" выводится до сообщения "победитель"; если победитель по какой то причине задерживается с выводом в консоль, другой поток успевает поймать interrupt из OnlineGame и быстренько выполнить свой блок catch.
0
ГоффMaster
2 октября 2022, 18:30
Так вот, твой код (или "правильный" код) не сработает правильно, если два потока практически одновременно придут к финишу. Победитель присвоит isWinnerFound true, второй останется ни с чем. Но и прерван по interrupt он не будет, потому что он не спит, он из сна одновременно с победителем уже вышел.
Соответственно, такой поток тихонечко завершится сам, без того, что бы выполнить catch, без вывода "проиграл".
Поэтому правильно будет добавить else, который бы отлавливал проигравшие, но ускользнувшие от interrupt потоки:
0