JUC之线程顺序打印 | Enplee's blog
0%

JUC之线程顺序打印

问题:实现T1,T2两个线程交替打印A1B2C3……

交替打印的实现,依赖于线程之间的有序阻塞和唤醒。可以用到的有:Synchronized的wait&notify,LockSupport的park&unpark,reentrenlock的condition以及CAS。

解法一:使用wait&notify

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Syn_wait_notify {
// 使用wait()和notify() 必须加锁synchronized才能使用
// wait() 会释放锁 for执行结束要notify使最后一个wait线程被唤醒 才能顺序结束
public static void main(String[] args) {
final Object o = new Object();
new Thread(()->{
synchronized (o){
for(int i=0;i<26;i++){
System.out.println((char)(i+'A'));
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
},"t1").start();

new Thread(()->{
synchronized (o){
for(int i=1;i<=26;i++){
System.out.println(i);
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
o.notify();
}
o.notify();
}
},"t2").start();
}
}

解法二 LockSupport: park&unpark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Lock_lockSupport {
static Thread t1 = null,t2 = null;
public static void main(String[] args) {
t1 = new Thread(()->{
for(int i=0;i<26;i++){
System.out.println((char)('A'+i));
LockSupport.unpark(t2);
LockSupport.park();
}
},"t1");
t2 = new Thread(()->{
for(int i=1;i<=26;i++){
LockSupport.park();
System.out.println(i);
LockSupport.unpark(t1);
}
},"t2");

t1.start();
t2.start();
}
}

解法三 condition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Lock_reenternLock_condition {
public static void main(String[] args) {
// Condition 本质上是不同的阻塞队列
// condition1.await() 将当前线程加入到condition1的阻塞队列中
// condition2.await() 将condition2阻塞队列中的线程唤醒
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();

new Thread(()->{
try {
lock.lock();

for (int i=0;i<26;i++){
System.out.println((char)(i+'A'));
condition2.signal();
condition1.await();
}
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
},"t1").start();

new Thread(()->{
try {
lock.lock();

for (int i=0;i<26;i++){
System.out.println(i);
condition1.signal();//唤醒condition1等待队列中的线程
condition2.await();//放到condition2这个等待队列
}
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
},"t2").start();
}
}

解法四:CAS 大道至简

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class cas_enum {
enum ReadyToRun {T1,T2}
static volatile ReadyToRun r = ReadyToRun.T1;

public static void main(String[] args) {
new Thread(()->{
for(int i=0;i<26;i++){
while (r!=ReadyToRun.T1) {}
System.out.println((char)('A'+i));
r = ReadyToRun.T2;
}
},"t1").start();

new Thread(()->{
for(int i=0;i<26;i++){
while (r!=ReadyToRun.T2) {}
System.out.println(i);
r = ReadyToRun.T1;
}
},"t2").start();
}
}
-------------本文结束感谢您的阅读-------------