Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ca059a5

Browse files
更新线程通信
1 parent a5f392d commit ca059a5

File tree

2 files changed

+233
-0
lines changed

2 files changed

+233
-0
lines changed
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
package com.javaedge.concurrency.common.communication;
2+
3+
import java.util.concurrent.locks.LockSupport;
4+
5+
import org.testng.annotations.Test;
6+
7+
/**
8+
* 三种线程协作通信的方式:suspend/resume、wait/notify、park/unpark
9+
*
10+
* @author JavaEdge
11+
* @date 2019年10月8日
12+
*/
13+
public class ThreadCommunication {
14+
15+
/**
16+
* 包子店
17+
*/
18+
public static Object bunShop = null;
19+
20+
/**
21+
* 正常的suspend/resume
22+
*/
23+
@Test
24+
public void suspendResumeTest() throws Exception {
25+
// 启动线程
26+
Thread consumerThread = new Thread(() -> {
27+
if (bunShop == null) {
28+
// 没包子,则进入等待
29+
System.out.println("1、进入等待");
30+
Thread.currentThread().suspend();
31+
}
32+
System.out.println("2、买到包子,回家");
33+
});
34+
consumerThread.start();
35+
// 3秒之后,生产一个包子
36+
Thread.sleep(3000L);
37+
bunShop = new Object();
38+
consumerThread.resume();
39+
System.out.println("3、通知消费者");
40+
}
41+
42+
/**
43+
* 死锁的suspend/resume。 suspend并不会像wait一样释放锁,容易写出死锁代码
44+
*/
45+
@Test
46+
public void suspendResumeDeadLockTest() throws Exception {
47+
// 启动线程
48+
Thread consumerThread = new Thread(() -> {
49+
if (bunShop == null) {
50+
// 没包子,则进入等待
51+
System.out.println("1、进入等待");
52+
// 当前线程拿到锁,然后挂起
53+
synchronized (this) {
54+
Thread.currentThread().suspend();
55+
}
56+
}
57+
System.out.println("2、买到包子,回家");
58+
});
59+
consumerThread.start();
60+
// 3秒之后,生产一个包子
61+
Thread.sleep(3000L);
62+
bunShop = new Object();
63+
// 争取到锁以后,再恢复consumerThread
64+
synchronized (this) {
65+
consumerThread.resume();
66+
}
67+
System.out.println("3、通知消费者");
68+
}
69+
70+
/**
71+
* 导致程序永久挂起的suspend/resume
72+
*/
73+
@Test
74+
public void suspendResumeDeadLockTest2() throws Exception {
75+
// 启动线程
76+
Thread consumerThread = new Thread(() -> {
77+
if (bunShop == null) {
78+
System.out.println("1、没包子,进入等待");
79+
try { // 为这个线程加上一点延时
80+
Thread.sleep(5000L);
81+
} catch (InterruptedException e) {
82+
e.printStackTrace();
83+
}
84+
// 这里的挂起执行在resume后面
85+
Thread.currentThread().suspend();
86+
}
87+
System.out.println("2、买到包子,回家");
88+
});
89+
consumerThread.start();
90+
// 3秒之后,生产一个包子
91+
Thread.sleep(3000L);
92+
bunShop = new Object();
93+
consumerThread.resume();
94+
System.out.println("3、通知消费者");
95+
consumerThread.join();
96+
}
97+
98+
/**
99+
* 正常的wait/notify
100+
*/
101+
@Test
102+
public void waitNotifyTest() throws Exception {
103+
// 启动消费者线程
104+
new Thread(() -> {
105+
if (bunShop == null) {
106+
// 如果没包子,则进入等待
107+
synchronized (this) {
108+
try {
109+
System.out.println("1、进入等待");
110+
this.wait();
111+
} catch (InterruptedException e) {
112+
e.printStackTrace();
113+
}
114+
}
115+
}
116+
System.out.println("2、买到包子,回家");
117+
}).start();
118+
// 3秒之后,生产一个包子
119+
Thread.sleep(3000L);
120+
bunShop = new Object();
121+
synchronized (this) {
122+
this.notifyAll();
123+
System.out.println("3、通知消费者");
124+
}
125+
}
126+
127+
/**
128+
* 会导致程序永久等待的wait/notify
129+
*/
130+
@Test
131+
public void waitNotifyDeadLockTest() throws Exception {
132+
// 启动线程
133+
new Thread(() -> {
134+
if (bunShop == null) { // 如果没包子,则进入等待
135+
try {
136+
Thread.sleep(5000L);
137+
} catch (InterruptedException e1) {
138+
e1.printStackTrace();
139+
}
140+
synchronized (this) {
141+
try {
142+
System.out.println("1、进入等待");
143+
this.wait();
144+
} catch (InterruptedException e) {
145+
e.printStackTrace();
146+
}
147+
}
148+
}
149+
System.out.println("2、买到包子,回家");
150+
}).start();
151+
// 3秒之后,生产一个包子
152+
Thread.sleep(3000L);
153+
bunShop = new Object();
154+
synchronized (this) {
155+
this.notifyAll();
156+
System.out.println("3、通知消费者");
157+
}
158+
}
159+
160+
/**
161+
* 正常的park/unpark
162+
*/
163+
@Test
164+
public void parkUnparkTest() throws Exception {
165+
// 启动线程
166+
Thread consumerThread = new Thread(() -> {
167+
if (bunShop == null) { // 如果没包子,则进入等待
168+
System.out.println("1、进入等待");
169+
LockSupport.park();
170+
}
171+
System.out.println("2、买到包子,回家");
172+
});
173+
consumerThread.start();
174+
// 3秒之后,生产一个包子
175+
Thread.sleep(3000L);
176+
bunShop = new Object();
177+
LockSupport.unpark(consumerThread);
178+
System.out.println("3、通知消费者");
179+
}
180+
181+
/**
182+
* 死锁的park/unpark
183+
*/
184+
@Test
185+
public void parkUnparkDeadLockTest() throws Exception {
186+
// 启动线程
187+
Thread consumerThread = new Thread(() -> {
188+
if (bunShop == null) { // 如果没包子,则进入等待
189+
System.out.println("1、进入等待");
190+
// 当前线程拿到锁,然后挂起
191+
synchronized (this) {
192+
LockSupport.park();
193+
}
194+
}
195+
System.out.println("2、买到包子,回家");
196+
});
197+
consumerThread.start();
198+
// 3秒之后,生产一个包子
199+
Thread.sleep(3000L);
200+
bunShop = new Object();
201+
// 争取到锁以后,再恢复consumerThread
202+
synchronized (this) {
203+
LockSupport.unpark(consumerThread);
204+
}
205+
System.out.println("3、通知消费者");
206+
}
207+
208+
public static void main(String[] args) throws Exception {
209+
// 对调用顺序有要求,也要开发自己注意锁的释放。这个被弃用的API, 容易死锁,也容易导致永久挂起。
210+
// new Demo6().suspendResumeTest();
211+
// new Demo6().suspendResumeDeadLockTest();
212+
// new Demo6().suspendResumeDeadLockTest2();
213+
214+
// wait/notify要求再同步关键字里面使用,免去了死锁的困扰,但是一定要先调用wait,再调用notify,否则永久等待了
215+
// new Demo6().waitNotifyTest();
216+
// new Demo6().waitNotifyDeadLockTest();
217+
218+
// park/unpark没有顺序要求,但是park并不会释放锁,所有再同步代码中使用要注意
219+
// new Demo6().parkUnparkTest();
220+
// new Demo6().parkUnparkDeadLockTest();
221+
222+
}
223+
}

‎pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@
8484
<artifactId>spring-rabbit</artifactId>
8585
<version>2.1.4.RELEASE</version>
8686
</dependency>
87+
<dependency>
88+
<groupId>org.springframework.boot</groupId>
89+
<artifactId>spring-boot-test</artifactId>
90+
</dependency>
91+
<dependency>
92+
<groupId>org.testng</groupId>
93+
<artifactId>testng</artifactId>
94+
<version>7.0.0-beta3</version>
95+
<scope>compile</scope>
96+
</dependency>
8797

8898
</dependencies>
8999

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /