order_print_num
问题分析:首先我们需要看清楚题目,多线程、顺序打印、然后就是几个线程交替顺序打印;
首先看下输出结果:
1
thread-0:0
2
thread-1:1
3
thread-2:2
4
thread-0:3
5
thread-1:4
6
thread-2:5
7
thread-0:6
8
thread-1:7
9
thread-2:8
10
thread-0:9
11
thread-1:10
12
thread-2:11
13
thread-0:12
14
thread-1:13
15
thread-2:14
16
thread-0:15
17
thread-1:16
18
thread-2:17
19
thread-0:18
20
thread-1:19
21
thread-2:20
22
thread-0:21
23
thread-1:22
24
thread-2:23
25
thread-0:24
26
thread-1:25
27
thread-2:26
28
thread-0:27
29
thread-1:28
30
thread-2:29
31
thread-0:30
32
thread-1:31
33
thread-2:32
34
thread-0:33
35
thread-1:34
36
thread-2:35
37
thread-0:36
38
thread-1:37
39
thread-2:38
40
thread-0:39
41
thread-1:40
42
thread-2:41
43
thread-0:42
44
thread-1:43
45
thread-2:44
46
thread-0:45
47
thread-1:46
48
thread-2:47
49
thread-0:48
50
thread-1:49
51
thread-2:50
52
thread-0:51
53
thread-1:52
54
thread-2:53
55
thread-0:54
56
thread-1:55
57
thread-2:56
58
thread-0:57
59
thread-1:58
60
thread-2:59
61
thread-0:60
62
thread-1:61
63
thread-2:62
64
thread-0:63
65
thread-1:64
66
thread-2:65
67
thread-0:66
68
thread-1:67
69
thread-2:68
70
thread-0:69
71
thread-1:70
72
thread-2:71
73
thread-0:72
74
thread-1:73
75
thread-2:74
76
thread-0:75
77
thread-1:76
78
thread-2:77
79
thread-0:78
80
thread-1:79
81
thread-2:80
82
thread-0:81
83
thread-1:82
84
thread-2:83
85
thread-0:84
86
thread-1:85
87
thread-2:86
88
thread-0:87
89
thread-1:88
90
thread-2:89
91
thread-0:90
92
thread-1:91
93
thread-2:92
94
thread-0:93
95
thread-1:94
96
thread-2:95
97
thread-0:96
98
thread-1:97
99
thread-2:98
100
thread-0:99
101
thread-1:100
Copied!
其实这个题目的重点就是怎么实现多个线程交替顺序打印,想一想,这里我们需要用到的就是线程间的通信,然后怎么通信呢?我们可以通过 synchronized + wait + notifyAll,或者 ReentrantLock + Condition + await + signalAll;
知道了线程间怎么通信,然后就是在每个线程内部怎么实现了,是不是多个线程共用一把锁,然后自然数0-100是公共资源,让3个线程去消费;
我们可以每个线程加上一个标号:0,1,2,来表示具体是哪个线程;通过一个计数器对3进行求余,余数和具体的线程标号去比较,只有当余数和线程标号相等的时候才进行打印(不等加入等待队列),打印完计数器进行自增;然后唤醒等待队列里面线程去获取锁,获取锁成功则继续执行以上步骤,否则加入锁的同步队列中,等待上一个线程唤醒;
用 synchronized 锁实现如下:
1
class PrintThread1 implements Runnable {
2
private static final Object LOCK = new Object();
3
4
private static int count = 0; // 计数,同时确定线程是否要加入等待队列,还是可以直接去资源队列里面去获取数据进行打印
5
private LinkedList<Integer> queue;
6
private Integer threadNo;
7
8
public PrintThread1(LinkedList<Integer> queue, Integer threadNo) {
9
this.queue = queue;
10
this.threadNo = threadNo;
11
}
12
13
@Override
14
public void run() {
15
while (true) {
16
synchronized (LOCK) {
17
while (count % 3 != this.threadNo) {
18
if (count >= 101) {
19
break;
20
}
21
try {
22
LOCK.wait();
23
} catch (InterruptedException e) {
24
e.printStackTrace();
25
}
26
}
27
28
if (count >= 101) {
29
break;
30
}
31
32
Integer val = this.queue.poll();
33
System.out.println("thread-" + this.threadNo + ":" + val);
34
count++;
35
36
LOCK.notifyAll();
37
}
38
}
39
}
40
}
Copied!
用 ReentrantLock 锁实现如下:
1
class PrintThread2 implements Runnable {
2
private static final ReentrantLock lock = new ReentrantLock();
3
private static final Condition c = lock.newCondition();
4
5
private static int count = 0; //作为计数,同时也作为资源;因为这道题目是自然数作为资源,所以正好可以公用;
6
private Integer threadNo;
7
8
public PrintThread2(Integer threadNo) {
9
this.threadNo = threadNo;
10
}
11
12
@Override
13
public void run() {
14
while (true) {
15
try {
16
lock.lock();
17
while (count % 3 != this.threadNo) {
18
if (count >= 101) {
19
break;
20
}
21
try {
22
c.await();
23
} catch (InterruptedException e) {
24
e.printStackTrace();
25
}
26
}
27
28
if (count >= 101) {
29
break;
30
}
31
System.out.println("thread-" + this.threadNo + ":" + count);
32
count++;
33
34
c.signalAll();
35
36
} finally {
37
lock.unlock();
38
}
39
}
40
}
41
}
Copied!
具体代码实现:
参见:code
Copy link