Skip to content

Commit 714b064

Browse files
committed
Add Livelock example
1 parent 341faa1 commit 714b064

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,5 @@ tasks.register('githubWorkflowTest', Test) {
8484
exclude '**/**AddMultithreadingTest.class'
8585
exclude '**/**BlockingQueueTest.class'
8686
exclude '**/**DeadlockTest.class'
87+
exclude '**/**LivelockTest.class'
8788
}

src/main/java/by/andd3dfx/multithreading/Deadlock.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import lombok.AllArgsConstructor;
44

55
/**
6-
* <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html">Example</a> from JDK
6+
* Taken from <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html">JDK docs</a>
77
*
88
* @see <a href="https://youtu.be/xuWU_6JTXi4">Video solution</a>
99
*/
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package by.andd3dfx.multithreading;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
7+
/**
8+
* Taken from <a href="https://github.com/proselytear/javaconcurrency">this repo</a>
9+
*/
10+
public class Livelock {
11+
12+
@Getter
13+
@Setter
14+
@AllArgsConstructor
15+
public static class Spoon {
16+
private Eater owner;
17+
18+
public synchronized void use() {
19+
System.out.printf("%s has eaten!", owner.getName());
20+
}
21+
}
22+
23+
@Getter
24+
public static class Eater {
25+
private String name;
26+
private boolean isHungry;
27+
28+
public Eater(String n) {
29+
name = n;
30+
isHungry = true;
31+
}
32+
33+
public void eatWith(Spoon spoon, Eater spouse) {
34+
while (isHungry) {
35+
// Don't have the spoon, so wait patiently for spouse.
36+
if (spoon.getOwner() != this) {
37+
try {
38+
Thread.sleep(10);
39+
} catch (InterruptedException e) {
40+
continue;
41+
}
42+
continue;
43+
}
44+
45+
// If spouse is hungry, insist upon passing the spoon.
46+
if (spouse.isHungry()) {
47+
System.out.printf(
48+
"%s: You eat first my darling %s!%n",
49+
name, spouse.getName());
50+
spoon.setOwner(spouse);
51+
continue;
52+
}
53+
54+
// Spouse wasn't hungry, so finally eat
55+
spoon.use();
56+
isHungry = false;
57+
System.out.printf(
58+
"%s: I am stuffed, my darling %s!%n",
59+
name, spouse.getName());
60+
spoon.setOwner(spouse);
61+
}
62+
}
63+
}
64+
65+
public void makeLivelock() {
66+
Eater husband = new Eater("Bob");
67+
Eater wife = new Eater("Alice");
68+
69+
Spoon s = new Spoon(husband);
70+
71+
Thread thread1 = new Thread(() -> husband.eatWith(s, wife));
72+
Thread thread2 = new Thread(() -> wife.eatWith(s, husband));
73+
74+
thread1.start();
75+
thread2.start();
76+
77+
while (thread1.isAlive() || thread2.isAlive()) ;
78+
}
79+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package by.andd3dfx.multithreading;
2+
3+
import org.junit.Test;
4+
5+
import java.util.concurrent.CompletableFuture;
6+
import java.util.concurrent.ExecutionException;
7+
8+
import static org.junit.Assert.assertFalse;
9+
10+
public class LivelockTest {
11+
12+
@Test
13+
public void makeLivelock() throws InterruptedException {
14+
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
15+
new Livelock().makeLivelock();
16+
return null;
17+
});
18+
19+
new Thread(() -> {
20+
try {
21+
future.get();
22+
System.out.println("Future completed!");
23+
} catch (InterruptedException | ExecutionException e) {
24+
throw new RuntimeException(e);
25+
}
26+
}).start();
27+
28+
// Wait 1 sec
29+
Thread.sleep(1000);
30+
31+
assertFalse("Should not be completed after 1 sec wait", future.isDone());
32+
}
33+
}

0 commit comments

Comments
 (0)