多线程实现按顺序循环输出ABC
2018-11-02 本文已影响13人
土豆肉丝盖浇饭
题目
今天一个朋友问了我一个题目,A,B,C三个线程,按照顺序,依次循环输出A,B,C字符。思路我大概是知道的,但是从来没实践过,既然是别人提出技术问题,那么我肯定是在所不辞的。
思路
让多线程之间按照顺序输出,那么可以考虑用锁控制对应顺序,B等待A释放锁,C等待B释放锁,我们的选择可以有CountDownLatch和CyclicBarrier,但是有循环的条件,所以应该选择可以重置的CyclicBarrier。
之后的思考就是如何通过CyclicBarrier实现C执行完后再执行A。
我的代码如下
public static void main(String[] args) {
final CyclicBarrier cyclicBarrier2 = new CyclicBarrier(2);
final CyclicBarrier cyclicBarrier3 = new CyclicBarrier(2);
final CyclicBarrier cyclicBarrier4 = new CyclicBarrier(3);
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
try {
while(true) {
System.out.println("A");
//控制A执行完在执行
cyclicBarrier2.await();
//等待ABC都运行完
cyclicBarrier4.await();
}
}catch (Exception ex){
ex.printStackTrace();
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
try {
while(true) {
cyclicBarrier2.await();
System.out.println("B");
//控制B执行完在执行C
cyclicBarrier3.await();
//等待ABC都运行完
cyclicBarrier4.await();
}
}catch (Exception ex){
ex.printStackTrace();
}
}
});
Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
try {
while(true) {
cyclicBarrier3.await();
System.out.println("C");
//等待ABC都运行完
cyclicBarrier4.await();
}
}catch (Exception ex){
ex.printStackTrace();
}
}
});
threadC.start();
threadB.start();
threadA.start();
}
对于CyclicBarrier需要注意一点,当打破屏障后,会自动重置,不需要手动调用它的reset方法(真是不试不知道)。
另外一种思路
使用SingleThreadExecutor能够保证线程顺序执行,其次每个线程执行完之后,再把自己放到线程池中去,那么就实现了循环。
按照题目的意思来讲,这个思路其实是不对的,因为实际上执行Runnable的线程都是同一个工作线程。哈哈哈。
public static void main(String[] args) {
final ExecutorService executorService = Executors.newSingleThreadExecutor();
Runnable runnableA =new Runnable() {
@Override
public void run() {
System.out.println("A");
executorService.execute(this);
}
};
Runnable runnableB =new Runnable() {
@Override
public void run() {
System.out.println("A");
executorService.execute(this);
}
};
Runnable runnableC =new Runnable() {
@Override
public void run() {
System.out.println("A");
executorService.execute(this);
}
};
executorService.execute(runnableA);
executorService.execute(runnableB);
executorService.execute(runnableC);
}
最后
还有什么实现方式呢。
还有下面是我的公众号。
image