Skip to content

Commit fec39d8

Browse files
authored
Merge pull request #5 from ahucoder/dev
The Multi-Threading Pattern
2 parents 73bc086 + 5004823 commit fec39d8

File tree

13 files changed

+733
-0
lines changed

13 files changed

+733
-0
lines changed

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<spring-boot-starter-web.version>3.4.5</spring-boot-starter-web.version>
1919
<guava.version>33.4.0-jre</guava.version>
2020
<commons-lang3.version>3.12.0</commons-lang3.version>
21+
<fastjson.version>2.0.12</fastjson.version>
2122
</properties>
2223

2324
<dependencies>
@@ -37,6 +38,7 @@
3738
<artifactId>guava</artifactId>
3839
<version>${guava.version}</version>
3940
</dependency>
41+
4042
<!-- JUnit 5 -->
4143
<dependency>
4244
<groupId>org.junit.jupiter</groupId>
@@ -56,6 +58,12 @@
5658
<version>${commons-lang3.version}</version>
5759
<scope>test</scope>
5860
</dependency>
61+
62+
<dependency>
63+
<groupId>com.alibaba</groupId>
64+
<artifactId>fastjson</artifactId>
65+
<version>${fastjson.version}</version>
66+
</dependency>
5967
</dependencies>
6068

6169
<build>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package multi_threading.fixed_operating_sequence;
2+
3+
import java.util.concurrent.locks.Condition;
4+
import java.util.concurrent.locks.ReentrantLock;
5+
6+
/**
7+
* Require always to run the t2 thread first before running other threads.
8+
*/
9+
public class FixedOperatingSequenceByLock {
10+
private static final ReentrantLock lock = new ReentrantLock();
11+
private static final Condition cond = lock.newCondition();
12+
private static boolean ready = false;
13+
14+
public static void main(String[] args) throws InterruptedException {
15+
new Thread(() -> {
16+
try {
17+
lock.lock();
18+
while (!ready) {
19+
try {
20+
cond.await();
21+
} catch (InterruptedException e) {
22+
throw new RuntimeException(e);
23+
}
24+
}
25+
} finally {
26+
lock.unlock();
27+
}
28+
System.out.println("t1 run...");
29+
}, "t1").start();
30+
31+
new Thread(() -> {
32+
try {
33+
lock.lock();
34+
System.out.println("t2 run...");
35+
ready = true;
36+
cond.signal();
37+
} finally {
38+
lock.unlock();
39+
}
40+
}, "t2").start();
41+
}
42+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package multi_threading.fixed_operating_sequence;
2+
3+
import java.util.concurrent.locks.LockSupport;
4+
5+
/**
6+
* Require always to run the t2 thread first before running other threads.
7+
*/
8+
public class FixedOperatingSequenceByPark {
9+
public static void main(String[] args) {
10+
Thread t1 = new Thread(() -> {
11+
LockSupport.park();
12+
System.out.println("t1 run...");
13+
}, "t1");
14+
t1.start();
15+
16+
new Thread(() -> {
17+
System.out.println("t2 run...");
18+
LockSupport.unpark(t1);
19+
}, "t2").start();
20+
}
21+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package multi_threading.fixed_operating_sequence;
2+
3+
/**
4+
* Require always to run the t2 thread first before running other threads.
5+
*/
6+
public class FixedOperatingSequenceByWaitNotify {
7+
private static final Object obj = new Object();
8+
private static boolean ready = false;
9+
10+
public static void main(String[] args) throws InterruptedException {
11+
new Thread(() -> {
12+
synchronized (obj) {
13+
while (!ready) {
14+
try {
15+
obj.wait();
16+
} catch (InterruptedException e) {
17+
throw new RuntimeException(e);
18+
}
19+
}
20+
System.out.println("t1 run...");
21+
}
22+
}, "t1").start();
23+
24+
new Thread(() -> {
25+
synchronized (obj) {
26+
System.out.println("t2 run...");
27+
ready = true;
28+
obj.notify();
29+
}
30+
}, "t2").start();
31+
}
32+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package multi_threading.guarded_suspension;
2+
3+
import com.alibaba.fastjson.JSONObject;
4+
import com.google.common.collect.Lists;
5+
6+
import java.util.List;
7+
8+
public class GuardedSuspensionMod {
9+
10+
@SuppressWarnings("unchecked")
11+
public static void main(String[] args) {
12+
GuardObject guardObject = new GuardObject();
13+
new Thread(() -> {
14+
System.out.println("waiting for result...");
15+
// List<String> o = (List<String>) guardObject.get();
16+
// List<String> o = (List<String>) guardObject.get(100);
17+
List<String> o = (List<String>) guardObject.get(3000);
18+
System.out.println(STR."result:\{JSONObject.toJSONString(o)}");
19+
}, "t1").start();
20+
21+
new Thread(() -> {
22+
System.out.println("process downloading...");
23+
guardObject.complete(new Download().downloadMock());
24+
}, "t2").start();
25+
}
26+
27+
}
28+
29+
class GuardObject {
30+
private Object response;
31+
32+
public Object get() {
33+
synchronized (this) {
34+
while (response == null) {
35+
try {
36+
this.wait();
37+
} catch (InterruptedException e) {
38+
throw new RuntimeException(e);
39+
}
40+
}
41+
return response;
42+
}
43+
}
44+
45+
/**
46+
* Waiting with timeout period,
47+
* The principle of the join method in Thread
48+
*
49+
* @param timeout
50+
* @return
51+
*/
52+
public Object get(long timeout) {
53+
synchronized (this) {
54+
long begin = System.currentTimeMillis();
55+
// elapsed time
56+
long passTime = 0;
57+
while (response == null) {
58+
try {
59+
// the time to wait for this cycle
60+
long waitTime = timeout - passTime;
61+
if (waitTime <= 0) {
62+
break;
63+
}
64+
this.wait(waitTime);
65+
passTime = System.currentTimeMillis() - begin;
66+
} catch (InterruptedException e) {
67+
throw new RuntimeException(e);
68+
}
69+
}
70+
return response;
71+
}
72+
}
73+
74+
public void complete(Object response) {
75+
synchronized (this) {
76+
this.response = response;
77+
this.notifyAll();
78+
}
79+
}
80+
}
81+
82+
class Download {
83+
public List<String> downloadMock() {
84+
try {
85+
//mock download progress
86+
Thread.sleep(2500);
87+
return buildMockResult();
88+
} catch (InterruptedException e) {
89+
throw new RuntimeException(e);
90+
}
91+
}
92+
93+
private List<String> buildMockResult() {
94+
String s = "success";
95+
List<String> res = Lists.newArrayList();
96+
res.add(s);
97+
return res;
98+
}
99+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package multi_threading.producer_consumer;
2+
3+
import lombok.Getter;
4+
import lombok.Setter;
5+
6+
@Setter
7+
@Getter
8+
public class Message {
9+
private int id;
10+
private String value;
11+
12+
@Override
13+
public String toString() {
14+
return STR."Message{id=\{id}, value='\{value}'}";
15+
}
16+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package multi_threading.producer_consumer;
2+
3+
import com.google.common.collect.Lists;
4+
5+
import java.util.List;
6+
7+
public class MessageQueue {
8+
public int capacity = 10;
9+
10+
private final List<Message> queue = Lists.newArrayList();
11+
12+
public Message take() {
13+
synchronized (queue) {
14+
while (queue.isEmpty()) {
15+
try {
16+
queue.wait();
17+
} catch (InterruptedException e) {
18+
throw new RuntimeException(e);
19+
}
20+
}
21+
Message message = queue.removeFirst();
22+
queue.notifyAll();
23+
return message;
24+
}
25+
}
26+
27+
public void put(Message message) {
28+
synchronized (queue) {
29+
while (queue.size() >= capacity) {
30+
try {
31+
queue.wait();
32+
} catch (InterruptedException e) {
33+
throw new RuntimeException(e);
34+
}
35+
}
36+
queue.add(message);
37+
queue.notifyAll();
38+
}
39+
}
40+
41+
public int size() {
42+
return queue.size();
43+
}
44+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package multi_threading.thread_alternate_running;
2+
3+
import java.util.concurrent.locks.Condition;
4+
import java.util.concurrent.locks.ReentrantLock;
5+
6+
public class ThreadAlternateRunningByLock {
7+
public static void main(String[] args) throws InterruptedException {
8+
AwaitSignal awaitSignalObj = new AwaitSignal(5);
9+
Condition a = awaitSignalObj.newCondition();
10+
Condition b = awaitSignalObj.newCondition();
11+
Condition c = awaitSignalObj.newCondition();
12+
13+
new Thread(() -> {
14+
awaitSignalObj.process("a", a, b);
15+
}, "t1").start();
16+
new Thread(() -> {
17+
awaitSignalObj.process("b", b, c);
18+
}, "t2").start();
19+
new Thread(() -> {
20+
awaitSignalObj.process("c", c, a);
21+
}, "t3").start();
22+
23+
Thread.sleep(1000);
24+
try {
25+
awaitSignalObj.lock();
26+
a.signal();
27+
} finally {
28+
awaitSignalObj.unlock();
29+
}
30+
}
31+
}
32+
33+
class AwaitSignal extends ReentrantLock {
34+
private final int loopNumber;
35+
36+
public AwaitSignal(int loopNumber) {
37+
this.loopNumber = loopNumber;
38+
}
39+
40+
public void process(String str, Condition current, Condition next) {
41+
for (int i = 0; i < loopNumber; i++) {
42+
lock();
43+
try {
44+
current.await();
45+
System.out.print(str);
46+
next.signal();
47+
} catch (InterruptedException e) {
48+
// Thread.currentThread().interrupt(); // restore interrupted state
49+
throw new RuntimeException(e);
50+
} finally {
51+
unlock();
52+
}
53+
}
54+
}
55+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package multi_threading.thread_alternate_running;
2+
3+
import java.util.concurrent.locks.LockSupport;
4+
5+
public class ThreadAlternateRunningByPark {
6+
static Thread t1;
7+
static Thread t2;
8+
static Thread t3;
9+
public static void main(String[] args) {
10+
ParkUnpark parkUnparkObj = new ParkUnpark(5);
11+
t1 = new Thread(() -> {
12+
parkUnparkObj.process("a", t2);
13+
}, "t1");
14+
t2 = new Thread(() -> {
15+
parkUnparkObj.process("b", t3);
16+
}, "t2");
17+
t3 = new Thread(() -> {
18+
parkUnparkObj.process("c", t1);
19+
}, "t3");
20+
t1.start();
21+
t2.start();
22+
t3.start();
23+
24+
LockSupport.unpark(t1);
25+
}
26+
}
27+
28+
class ParkUnpark {
29+
private final int loopNumber;
30+
ParkUnpark(int loopNumber) {
31+
this.loopNumber = loopNumber;
32+
}
33+
34+
public void process(String str, Thread t) {
35+
for (int i = 0; i < loopNumber; i++) {
36+
LockSupport.park();
37+
System.out.print(str);
38+
LockSupport.unpark(t);
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)