如何实现ABC三个线程按顺序执行十次
Posted 张维鹏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现ABC三个线程按顺序执行十次相关的知识,希望对你有一定的参考价值。
题目要求:创建三个线程,每个线程分别打印ABC,并按照ABC的顺序执行十次
题目可以使用多种不同的方式解决,下面我们分别使用 Condition 等待唤醒机制、Semaphore 信号量、CountDownLatch 闭锁、Thread.join() 方法四种方式实现题目要求。
一、使用一个 ReentrantLock 和 三个 Condition 来实现:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* 题目要求:ABC三个线程顺序执行10次
* 实现思路:使用一个ReentrantLock 和 三个 Condition 来实现
*/
public class PrintABCUsingCondition
{
private static ReentrantLock lock = new ReentrantLock();
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();
private static Condition conditionC = lock.newCondition();
public void execute(String flag)
{
lock.lock();
for (int i = 1 ; i <= 10 ; i++){
if ("A".equals(flag)) print(flag, conditionA, conditionB);
if ("B".equals(flag)) print(flag, conditionB, conditionC);
if ("C".equals(flag)) print(flag, conditionC, conditionA);
}
lock.unlock();
}
private void print(String name, Condition currentThread, Condition nextThread)
{
try{
System.out.println(Thread.currentThread().getName() + "-" + name);
nextThread.signal();
currentThread.await();
}catch (InterruptedException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException
{
PrintABCUsingCondition myTask = new PrintABCUsingCondition();
new Thread(() -> myTask.execute("A")).start();
//必须确保线程A比另外两个线程先拿到ReentrantLock,所以让主线程sleep一段时间
Thread.sleep(500);
new Thread(() -> myTask.execute("B")).start();
new Thread(() -> myTask.execute("C")).start();
}
}
二、基于 Semaphore 信号量来实现:
import java.util.concurrent.Semaphore;
/**
* 题目要求:ABC三个线程顺序执行10次
* 实现思路:使用一个Semaphore信号量来实现
*/
class PrintABCUsingSemaphore
{
private Semaphore semaphoreA = new Semaphore(1);
private Semaphore semaphoreB = new Semaphore(0);
private Semaphore semaphoreC = new Semaphore(0);
private void printA(){
print("A", semaphoreA, semaphoreB);
}
private void printB(){
print("B", semaphoreB, semaphoreC);
}
private void printC(){
print("C", semaphoreC, semaphoreA);
}
private void print(String name, Semaphore currentSemaphore, Semaphore nextSemaphore)
{
for (int i = 0; i < 10; i++){
try {
currentSemaphore.acquire();
System.out.println(Thread.currentThread().getName() +" print "+ name);
nextSemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
PrintABCUsingSemaphore printABC = new PrintABCUsingSemaphore();
new Thread(() -> printABC.printA()).start();
new Thread(() -> printABC.printB()).start();
new Thread(() -> printABC.printC()).start();
}
}
三、基于 CountDownLatch 闭锁来实现:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
/**
* 题目要求:ABC三个线程顺序执行10次
* 实现思路:使用 CountDownLatch 来实现:
* (1)定义dependLatch(所依赖的latch名)、selfLatch(自己的latch名)
* (2)首先调用所依赖的latch的await()方法,如果所依赖的latch的count为0,则重置所依赖的latch并打印需要输出的,最后将自身的count减去
* (3)sum为需要执行的次数
*/
public class PrintABCUsingCountDownLatch implements Runnable {
private static Map<String, CountDownLatch> countDownLatchMap = new HashMap<>();
private String dependLatch;
private String selfLatch;
private PrintABCUsingCountDownLatch(String dependLatch, String selfLatch)
{
this.dependLatch = dependLatch;
this.selfLatch = selfLatch;
}
@Override
public void run()
{
for (int i = 0; i < 10; i++)
{
try {
countDownLatchMap.get(dependLatch).await();
countDownLatchMap.put(dependLatch, new CountDownLatch(1));
System.out.println(Thread.currentThread().getName() + ":" + selfLatch);
countDownLatchMap.get(selfLatch).countDown();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
String latchA = "A";
String latchB = "B";
String latchC = "C";
countDownLatchMap.put(latchA, new CountDownLatch(1));
countDownLatchMap.put(latchB, new CountDownLatch(1));
countDownLatchMap.put(latchC, new CountDownLatch(1));
//创建三个线程,但是此时由于三个CountDownLatch都不为0,所以三个线程都处于阻塞状态
Thread threadA = new Thread(new PrintABCUsingCountDownLatch(latchC, latchA));
Thread threadB = new Thread(new PrintABCUsingCountDownLatch(latchA, latchB));
Thread threadC = new Thread(new PrintABCUsingCountDownLatch(latchB, latchC));
threadA.start();
threadB.start();
threadC.start();
//latchC 阻塞了 latchA;调用latchC的countDown()方法,先让latchC为0,使latchA先运行
countDownLatchMap.get(latchC).countDown();
}
四、 使用 Thread.join() 方法来实现:
/**
* 题目要求:ABC三个线程顺序执行10次
* 实现思路:使用 Thread.join() 方法来实现
*/
public class PrintABCUsingJoin
{
public static void main(String[] args)
{
Thread t0 = new Thread(new Work((null)));
Thread t1 = new Thread(new Work((t0)));
Thread t2 = new Thread(new Work((t1)));
t0.start();
t1.start();
t2.start();
}
}
class Work implements Runnable
{
private Thread beforeThread;
public Work(Thread beforeThread)
{
this.beforeThread = beforeThread;
}
@Override
public void run()
{
//调用前面线程的join方法
if(beforeThread != null)
{
try{
beforeThread.join();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前线程:" + Thread.currentThread().getName());
}
}
以上是关于如何实现ABC三个线程按顺序执行十次的主要内容,如果未能解决你的问题,请参考以下文章