固定运行顺序
wait-notify 实现
采用 wait-notify 机制可以实现对线程执行顺序的控制,我们只需要一个执行标志即可,如下代码所示:
public class WaitNotify {
// 用来同步的对象
static Object obj = new Object();
// t2 运行标记, 代表 t2 是否执行过
static boolean t2runed = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (obj) {
// 如果 t2 没有执行过
while (!t2runed) {
try {
// t1 先等一会
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(1);
});
Thread t2 = new Thread(() -> {
System.out.println(2);
synchronized (obj) {
// 修改运行标记
t2runed = true;
// 通知 obj 上等待的线程(可能有多个,因此需要用 notifyAll)
obj.notifyAll();
}
});
t1.start();
t2.start();
}
}
park-unpark 实现
public class ParkUnpark {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
LockSupport.park();
System.out.println("1");
}, "t1");
Thread t2 = new Thread(() -> {
System.out.println("2");
LockSupport.unpark(t1);
}, "t2");
t1.start();
t2.start();
}
}
交替运行顺序
要求依次“线程1输出a,线程2输出b,线程3输出c”,这样循环5次。即利用三个线程输出“abcabcabcabcabc”这样的结构。
wait-notify 实现
public class SyncWaitNotify {
private int flag;
private final int loopNums;
public SyncWaitNotify(int flag, int loopNums) {
this.flag = flag;
this.loopNums = loopNums;
}
@SneakyThrows
public void print(int curFlag, int nextFlag, String content) {
for (int i = 0; i < loopNums; i++) {
synchronized (this) {
//如果curFlag 和当前线程执行 flag 不相同
while (this.flag != curFlag) {
wait();
}
System.out.print(content);
flag = nextFlag;
notifyAll();
}
}
}
public static void main(String[] args) {
SyncWaitNotify syncWaitNotify = new SyncWaitNotify(1, 5);
//线程1打印 a -->flag=1
new Thread(() -> {
syncWaitNotify.print(1, 2, "a");
}).start();
//线程2打印 b -->flag=2
new Thread(() -> {
syncWaitNotify.print(2, 3, "b");
}).start();
//线程3打印 c -->flag=3
new Thread(() -> {
syncWaitNotify.print(3, 1, "c");
}).start();
}
}
await-signal 实现
public class AwaitSignal extends ReentrantLock {
// 循环次数
private final int loopNumber;
public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}
public void start(Condition first) {
this.lock();
try {
first.signal();
} finally {
this.unlock();
}
}
public void print(String str, Condition current, Condition next) {
for (int i = 0; i < loopNumber; i++) {
this.lock();
try {
current.await();
System.out.print(str);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.unlock();
}
}
}
public static void main(String[] args) {
AwaitSignal as = new AwaitSignal(5);
//线程1的等待室
Condition aWaitSet = as.newCondition();
//线程2的等待室
Condition bWaitSet = as.newCondition();
//线程3的等待室
Condition cWaitSet = as.newCondition();
//线程1打印 a
new Thread(() -> {
as.print("a", aWaitSet, bWaitSet);
}).start();
//线程2打印 b
new Thread(() -> {
as.print("b", bWaitSet, cWaitSet);
}).start();
//线程3打印 c
new Thread(() -> {
as.print("c", cWaitSet, aWaitSet);
}).start();
//先唤醒 aWaitSet 中的线程1
as.start(aWaitSet);
}
}
park-unpark 实现
public class SyncPark {
private final int loopNumber;
private Thread[] threads;
public SyncPark(int loopNumber) {
this.loopNumber = loopNumber;
}
public void setThreads(Thread... threads) {
this.threads = threads;
}
public void print(String str) {
for (int i = 0; i < loopNumber; i++) {
LockSupport.park();
System.out.print(str);
//输出str后,让下一个线程运行
LockSupport.unpark(nextThread());
}
}
private Thread nextThread() {
Thread current = Thread.currentThread();
int index = 0;
for (int i = 0; i < threads.length; i++) {
if (threads[i] == current) {
index = i;
break;
}
}
if (index < threads.length - 1) {
return threads[index + 1];
} else {
return threads[0];
}
}
public void start() {
for (Thread thread : threads) {
thread.start();
}
//先让 threads[0] 执行
LockSupport.unpark(threads[0]);
}
public static void main(String[] args) {
SyncPark syncPark = new SyncPark(5);
Thread t1 = new Thread(() -> {
syncPark.print("a");
});
Thread t2 = new Thread(() -> {
syncPark.print("b");
});
Thread t3 = new Thread(() -> {
syncPark.print("c");
});
syncPark.setThreads(t1, t2, t3);
syncPark.start();
}
}