Java多线程-顺序&交替输出

固定运行顺序

问题:先打印2后打印1

  1. 使用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
package juc.thread;

/**
* @Author qq
* @Date 2022/3/18
*/
public class shunxu {
static Object lock = new Object();
static boolean flag = false;//2还没有打印
public static void main(String[] args) {
Thread thread = new Thread(() -> {
synchronized (lock){
while(!flag){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("1");
}

},"t1");

Thread thread2 = new Thread(() -> {
synchronized (lock){
System.out.println("2");
flag = true;//2已经打印了
lock.notify();
}
},"t2");
thread.start();
thread2.start();
}
}

  1. 使用park()和unpark()组合

park()和unpark()以线程为单位来阻塞和唤醒线程,而notify只能随机唤醒一个线程。

  • 先调用park(),再调用unpark():如果counter=0,则线程进入阻塞队列,调用unpark(),counter=1,线程继续运行,再次赋值counter=0

  • 先调用unpark(),再调用park():线程正在运行,赋值counter=1,调用park(),赋值counter=0,线程不停止运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class shunxu {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
LockSupport.park();
System.out.println("1");
},"t1");

Thread thread2 = new Thread(() -> {
System.out.println("2");
LockSupport.unpark(thread);
},"t2");
thread.start();
thread2.start();
}
}

交替输出

问题:交替输出abc,假设循环5次,则输出结果是abcabcabcabcabc

  1. 使用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
38
39
40
41
42
public class shunxu {
public static void main(String[] args) {
waitnotify a1 = new waitnotify(1,5);
new Thread(()->{
a1.print("a",1,2);
}).start();
new Thread(()->{
a1.print("b",2,3);
}).start();
new Thread(()->{
a1.print("c",3,1);
}).start();
}


}
class waitnotify{
static int flag;
static int num;
public waitnotify(int flag,int num){
this.num = num;
this.flag = flag;
}

public void print(String str,int flag,int nextflag){
for (int i = 0; i < num; i++) {
synchronized (this){
while(!(flag == this.flag)){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str);
this.flag = nextflag;
this.notifyAll();
}
}
}
}

  1. 使用ReentrantLock,创建多个休息室,先让所有线程进入休息室等待,主线程唤醒一个线程。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package juc.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
* @Author qq
* @Date 2022/3/18
*/
public class shunxu {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
waitnotify a1 = new waitnotify(5,lock);

new Thread(()->{
a1.print("a",c1,c2);
}).start();
new Thread(()->{
a1.print("b",c2,c3);
}).start();
new Thread(()->{
a1.print("c",c3,c1);
}).start();

lock.lock();
try{
c1.signal();
}finally {
lock.unlock();
}

}


}
class waitnotify{
int num;
static ReentrantLock lock;
public waitnotify(int num,ReentrantLock lock){
this.num = num;
this.lock = lock;
}

public void print(String str, Condition c1,Condition c2){
for (int i = 0; i < num; i++) {
lock.lock();
try{
c1.await();
System.out.print(str);
c2.signal();
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}

  1. 三个线程交替输出1~99

重点在于设置volatile保证共享变量的可见性和有序性。

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
45
46
47
48
49
50
51
52
53
54
55
package juc.thread;

/**
* @Author qq
* @Date 2022/3/12
*/
//3个线程交替打印 1 2 3
public class parctice {

public static void main(String[] args) {
waitNotify w = new waitNotify(1,1);
new Thread(()->{
w.print(1,2);
},"t1").start();
new Thread(()->{
w.print(2,3);
},"t2").start();
new Thread(()->{
w.print(3,1);
},"t3").start();
}
}
class waitNotify{
private int flag;
private volatile int res;

public waitNotify(int flag,int res){
this.flag = flag;
this.res = res;
}

public void print(int flag,int nextflag){
while(res < 100) {
synchronized (this){
while(!(flag == this.flag)){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(res > 99){
return;
}
System.out.println(Thread.currentThread().getName()+"["+res+"]");
synchronized (this){
res++;
this.flag = nextflag;
notifyAll();
}
}
}
}
}


Java多线程-顺序&交替输出
https://vickkkyz.fun/2022/03/24/Java/JUC/交替和顺序输出/
作者
Vickkkyz
发布于
2022年3月24日
许可协议