问题1:4个线程交替打印ABCD
方案一:
用CyclicBarrir和CountDownLatch, CountDownLatch起到hold住所有线程的作用,每个线程判断barrier上的waitingNumber来决定是否打印,每个线程都是死循环。
public static void main(String... args) {
CountDownLatch countDownLatch = new CountDownLatch(1);
//4个线程交替打印ABCD
CyclicBarrier cyclicBarrier = new CyclicBarrier(4, () -> {
logger.info("开始新的一轮打印");
});
Thread athread = new Thread(() -> {
try {
//先暂停住
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("开始执行");
while (true) {
try {
if (cyclicBarrier.getNumberWaiting() == 0) {
logger.info("A");
cyclicBarrier.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}, "athread");
Thread bthread = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("开始执行");
while (true) {
try {
if (cyclicBarrier.getNumberWaiting() == 1) {
logger.info("B");
cyclicBarrier.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}, "bthread");
Thread cthread = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("开始执行");
while (true) {
try {
if (cyclicBarrier.getNumberWaiting() == 2) {
logger.info("C");
cyclicBarrier.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}, "cthread");
Thread dthread = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("开始执行");
while (true) {
try {
if (cyclicBarrier.getNumberWaiting() == 3) {
logger.info("D");
cyclicBarrier.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}, "dthread");
athread.start();
bthread.start();
cthread.start();
dthread.start();
//让子线程全部运行
countDownLatch.countDown();
sleep(10000000L);
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果:
2020-07-15 14:04:35,508 INFO [athread] com.x.order.service.NormalTest.lambda$main$1(1577) - A
2020-07-15 14:04:35,508 INFO [bthread] com.x.order.service.NormalTest.lambda$main$2(1597) - B
2020-07-15 14:04:35,508 INFO [cthread] com.x.order.service.NormalTest.lambda$main$3(1617) - C
2020-07-15 14:04:35,508 INFO [dthread] com.x.order.service.NormalTest.lambda$main$4(1638) - D
2020-07-15 14:04:35,508 INFO [dthread] com.x.order.service.NormalTest.lambda$main$0(1564) - 开始新的一轮打印
2020-07-15 14:04:35,508 INFO [athread] com.x.order.service.NormalTest.lambda$main$1(1577) - A
2020-07-15 14:04:35,508 INFO [bthread] com.x.order.service.NormalTest.lambda$main$2(1597) - B
2020-07-15 14:04:35,508 INFO [cthread] com.x.order.service.NormalTest.lambda$main$3(1617) - C
2020-07-15 14:04:35,508 INFO [dthread] com.x.order.service.NormalTest.lambda$main$4(1638) - D
这种方式的缺点:4个线程一直在运行,cpu使用率高。
方案二:
用4个Condition,每个后面的线程需要被前一个线程唤醒;刚开始的时候a线程由main线程唤醒。
public static void main(String... args) {
Lock lock = new ReentrantLock();
final Condition aCondition = lock.newCondition();
final Condition bCondition = lock.newCondition();
final Condition cCondition = lock.newCondition();
final Condition dCondition = lock.newCondition();
Thread athread = new Thread(() -> {
//先停住
lock.lock();
try {
aCondition.await();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
while (true) {
lock.lock();
try {
logger.info("A");
// 通知b线程运行, b线程会尝试获取锁,但是a线程还没把锁释放,b会一直等待
bCondition.signalAll();
//a线程释放锁,同事加入aCondition的等待队列。当d线程调用aCondition.signall()的时候,a线程会再次尝试获取锁,然后从下一行代码继续运行
aCondition.await();
logger.info("新一轮打印开始");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "athread");
Thread bthread = new Thread(() -> {
lock.lock();
try {
bCondition.await();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
while (true) {
lock.lock();
try {
logger.info("B");
cCondition.signalAll();
bCondition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "bthread");
Thread cthread = new Thread(() -> {
lock.lock();
try {
cCondition.await();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
while (true) {
lock.lock();
try {
logger.info("C");
dCondition.signalAll();
cCondition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "cthread");
Thread dthread = new Thread(() -> {
lock.lock();
try {
dCondition.await();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
while (true) {
lock.lock();
try {
logger.info("D");
aCondition.signalAll();
dCondition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "dthread");
athread.start();
bthread.start();
cthread.start();
dthread.start();
lock.lock();
try{
aCondition.signalAll();
}finally {
lock.unlock();
}
sleep(10000000L);
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果:
2020-07-15 14:47:58,411 INFO [athread] com.x.order.service.NormalTest.lambda$main$0(1581) - A
2020-07-15 14:47:58,411 INFO [bthread] com.x.order.service.NormalTest.lambda$main$1(1605) - B
2020-07-15 14:47:58,411 INFO [cthread] com.x.order.service.NormalTest.lambda$main$2(1628) - C
2020-07-15 14:47:58,411 INFO [dthread] com.x.order.service.NormalTest.lambda$main$3(1652) - D
2020-07-15 14:47:58,411 INFO [athread] com.x.order.service.NormalTest.lambda$main$0(1584) - 新一轮打印开始
2020-07-15 14:47:58,411 INFO [athread] com.x.order.service.NormalTest.lambda$main$0(1581) - A
2020-07-15 14:47:58,411 INFO [bthread] com.x.order.service.NormalTest.lambda$main$1(1605) - B
2020-07-15 14:47:58,411 INFO [cthread] com.x.order.service.NormalTest.lambda$main$2(1628) - C
2020-07-15 14:47:58,411 INFO [dthread] com.x.order.service.NormalTest.lambda$main$3(1652) - D
网友评论