feat(concurrency): replace livelock example with corridor scenario
This commit is contained in:
@@ -1,36 +1,99 @@
|
|||||||
package com.example;
|
package com.example;
|
||||||
|
|
||||||
import com.example.util.ThreadUtils;
|
|
||||||
|
|
||||||
public class LiveLock {
|
public class LiveLock {
|
||||||
|
|
||||||
private static boolean thread1WantsToPass = true;
|
static class Corridor {
|
||||||
private static boolean thread2WantsToPass = true;
|
private Person currentPerson;
|
||||||
|
|
||||||
|
public Corridor(Person person) {
|
||||||
|
currentPerson = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setPerson(Person person) {
|
||||||
|
currentPerson = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void pass() {
|
||||||
|
System.out.printf("%s прошёл по коридору!%n", currentPerson.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Person {
|
||||||
|
private String name;
|
||||||
|
private boolean wantsToPass;
|
||||||
|
|
||||||
|
public Person(String personName) {
|
||||||
|
name = personName;
|
||||||
|
wantsToPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wantsToPass() {
|
||||||
|
return wantsToPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void walkThrough(Corridor corridor, Person otherPerson) {
|
||||||
|
while (wantsToPass) {
|
||||||
|
|
||||||
|
// Если сейчас право пройти принадлежит другому человеку,
|
||||||
|
// немного ждём и снова проверяем ситуацию.
|
||||||
|
if (corridor.currentPerson != this) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если второй человек тоже хочет пройти,
|
||||||
|
// вежливо уступаем ему дорогу.
|
||||||
|
if (otherPerson.wantsToPass()) {
|
||||||
|
System.out.printf("%s: Проходи первым, %s!%n", name, otherPerson.getName());
|
||||||
|
|
||||||
|
corridor.setPerson(otherPerson);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если другой человек уже прошёл,
|
||||||
|
// наконец сами идём по коридору.
|
||||||
|
corridor.pass();
|
||||||
|
wantsToPass = false;
|
||||||
|
|
||||||
|
System.out.printf("%s: Спасибо, %s!%n", name, otherPerson.getName());
|
||||||
|
|
||||||
|
corridor.setPerson(otherPerson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Thread thread1 =
|
|
||||||
new Thread(
|
final Person ivan = new Person("Иван");
|
||||||
() -> {
|
final Person petr = new Person("Пётр");
|
||||||
while (thread1WantsToPass) {
|
|
||||||
System.out.println("Поток 1: Я уступаю дорогу Потоку 2...");
|
// Изначально право пройти по коридору принадлежит Ивану.
|
||||||
ThreadUtils.sleep(100);
|
final Corridor corridor = new Corridor(ivan);
|
||||||
|
|
||||||
|
// Первый поток — Иван.
|
||||||
|
new Thread(
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
ivan.walkThrough(corridor, petr);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
|
||||||
System.out.println("Поток 1 прошел!");
|
// Второй поток — Пётр.
|
||||||
});
|
new Thread(
|
||||||
|
new Runnable() {
|
||||||
Thread thread2 =
|
public void run() {
|
||||||
new Thread(
|
petr.walkThrough(corridor, ivan);
|
||||||
() -> {
|
|
||||||
while (thread2WantsToPass) {
|
|
||||||
System.out.println("Поток 2: Я уступаю дорогу Потоку 1...");
|
|
||||||
ThreadUtils.sleep(100);
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
System.out.println("Поток 2 прошел!");
|
.start();
|
||||||
});
|
|
||||||
|
|
||||||
thread1.start();
|
|
||||||
thread2.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user