同步模式之顺序控制
必须先 2 后 1 打印
使用wait notify
@Slf4j
public class SequenceWait {
static Object obj = new Object();
// 判断t2是否已经运行
static boolean ist2runned = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (obj){
// 当t2正在运行时,t1进入等待
while (!ist2runned){
try{
obj.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
log.info("t1 start....");
}
});
Thread t2 = new Thread(() -> {
log.info("t2 start....");
synchronized (obj){
ist2runned = true;
// 通知等待的线程
obj.notifyAll();
}
});
t1.start();
t2.start();
}
}
执行结果

使用park unpark
- 使用wait和notify的方式需要保证先wait后notify,否则wait永远得不到唤醒,需要【运行标记】去判断需不需要wait
- 使用while防止虚假唤醒
- 唤醒对象上的wait需要使用notifyAll,防止等待线程不止一个
public static void main(String[] args) {
Thread t1 = new Thread(()->{
LockSupport.park();
log.info("t1 start ....");
},"t1");
Thread t2 = new Thread(()->{
log.info("t2 start ....");
LockSupport.unpark(t1);
},"t2");
t1.start();
t2.start();
}

使用了park和unpark,利用了以线程为单位的特点,不需要【同步对象】和【运行标记】
交替输出
使用wait和notifyAll
@Slf4j
public class SyncWaitNotify {
private int flag;
// 循环次数
private int loopNumber;
public SyncWaitNotify(int flag, int loopNumber) {
this.flag = flag;
this.loopNumber = loopNumber;
}
public void print(int waitFlag, int nextFlag, String str){
for(int i=0;i<loopNumber;i++){
synchronized (this){
while(this.flag != waitFlag){
try {
this.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
log.info(str);
flag = nextFlag;
this.notifyAll();
}
}
}
}
public static void main(String[] args) {
SyncWaitNotify sn = new SyncWaitNotify(1,5);
new Thread(()->{
sn.print(1,2,"a");
}).start();
new Thread(()-> {
sn.print(2, 3, "b");
}).start();
new Thread(()->{
sn.print(3,1,"c");
}).start();
}

条件变量
@Slf4j
public class AwaitSync extends ReentrantLock {
// 循环次数
private int loopNumber;
public AwaitSync(int loopNumber){
this.loopNumber = loopNumber;
}
public void print(String str, Condition current, Condition next){
for(int i=0; i<loopNumber; i++){
this.lock();
try {
current.await();
log.info(str);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.unlock();
}
}
}
public void start(Condition first){
this.lock();
try {
log.info("start....");
first.signal();
}finally {
this.unlock();
}
}
}
public static void main(String[] args) {
AwaitSync as = new AwaitSync(5);
Condition aAwait = as.newCondition();
Condition bAwait = as.newCondition();
Condition cAwait = as.newCondition();
new Thread(()->{
as.print("a",aAwait,bAwait);
}).start();
new Thread(()->{
as.print("b",bAwait,cAwait);
}).start();
new Thread(()->{
as.print("c",cAwait,aAwait);
}).start();
as.start(aAwait);
}

使用park unpark
static Thread t1;
static Thread t2;
static Thread t3;
public static void main(String[] args) {
SyncPark syncPark = new SyncPark(5);
t1 = new Thread(()->{
syncPark.print("a",t2);
});
t2 = new Thread(()->{
syncPark.print("b",t3);
});
t3 = new Thread(()->{
syncPark.print("c",t1);
});
t1.start();
t2.start();
t3.start();
LockSupport.unpark(t1);
}
@Slf4j
public class SyncPark {
private int loopNumber;
public SyncPark(int loopNumber) {
this.loopNumber = loopNumber;
}
public void print(String str,Thread next){
for(int i=0; i<loopNumber; i++){
LockSupport.park();
log.info(str);
LockSupport.unpark(next);
}
}
}

1万+

被折叠的 条评论
为什么被折叠?



