问题
题目如下:控制三个线程ABC,A打印1,B打印2,C打印3;要求是每个线程交替打印5次,即按123123……的顺序打印。
解决方案:
1.wait¬ify
public class Example {
public static Object lock = new Object();//锁对象
public static int flag = 1; //标志位初始为1,即先打印1
public static void main(String[] args) {
new Thread(() -> {
int count1 = 0; //计数器
while (count1 < 5) {
synchronized (lock) {
if (flag == 1) { //如果标记是当前线程则输出
log.debug("{}", 1);
flag = 2; //标记改为下一个输出的线程
count1++; //计数器加一
sleep(1000);
lock.notifyAll(); //唤醒所以线程,提示他们"可能到你输出了"
} else { //不是当前线程输出,则进入WaitSet等待
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}, "t1").start();
new Thread(() -> {
int count2 = 0;
while (count2 < 5) {
synchronized (lock) {
if (flag == 2) {
log.debug("{}", 2);
flag = 3;
count2++;
sleep(1000);
lock.notifyAll();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}, "t2").start();
new Thread(() -> {
int count3 = 0;
while (count3 < 5) {
synchronized (lock) {
if (flag == 3) {
log.debug("{}", 3);
flag = 1;
count3++;
sleep(1000);
lock.notifyAll();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}, "t3").start();
}
public static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.await&signal
ReentrantLock和synchronized的相似,但是ReentrantLock可以使用多个条件变量
@Slf4j
public class Example {
public static Lock lock = new ReentrantLock();//ReentrantLock锁对象
//设置3个条件变量,即3个WaitSet
public static Condition condition1 = lock.newCondition();
public static Condition condition2 = lock.newCondition();
public static Condition condition3 = lock.newCondition();
public static int flag = 1;
public static void main(String[] args) {
new Thread(() -> {
int count = 0;
while (count < 5) {
lock.lock();
try {
if (flag == 1) {
log.debug("{}", 1);
flag = 2;
count++;
condition2.signal();
} else {
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}, "A").start();
new Thread(() -> {
int count = 0;
while (count < 5) {
lock.lock();
try {
if (flag == 2) {
log.debug("{}", 2);
flag = 3;
count++;
condition3.signal();
} else {
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}, "B").start();
new Thread(() -> {
int count = 0;
while (count < 5) {
lock.lock();
try {
if (flag == 3) {
log.debug("{}", 3);
flag = 1;
count++;
condition1.signal();
} else {
try {
condition3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}, "A").start();
}
}
3.pack&unpack
@Slf4j
public class Example {
public static Thread A, B, C;
public static void main(String[] args) throws InterruptedException {
A = new Thread(() -> {
int count = 0;
while (count < 5) {
LockSupport.park();
log.debug("{}", 1);
count++;
LockSupport.unpark(B);
}
}, "A");
A.start();
B = new Thread(() -> {
int count = 0;
while (count < 5) {
LockSupport.park();
count++;
log.debug("{}", 2);
LockSupport.unpark(C);
}
}, "B");
B.start();
C = new Thread(() -> {
int count = 0;
while (count < 5) {
LockSupport.park();
log.debug("{}", 3);
count++;
LockSupport.unpark(A);
}
}, "C");
C.start();
LockSupport.unpark(A);
}
}