Java多线程交替执行任务

时间:2023-02-25 18:36:31

一:问题描述

         生活中很多事情都是有顺序的交互进行着,比如100个人去做地铁,安检的只负责安;只有安检通过了,才能排队刷卡进站;进站了,在对应线路站下排队才能进站。这就是一个典型的多任务有顺序的进行。对于每一个人来说都有顺序要经过这几步。

        我们可以通过程序简单的抽象成,使用三个线程,每个线程分别只打印A、B、C. 依次打印出十组ABC.

二:实现思路:

         这是一个典型的同步多条件的线程问题。同步肯定要用到Lock锁, 多条件就要用到Condition。

          a)我们先抽象一个打印类,负责具体的A,B,C的打印.里边有个对象锁,同事有三个分支条件Condition,里边有一个变量代表当前打印的类型是A,B,C。打印具体的一个字母时候,判断下当前变量是不是这个字母的,不是就把当前条件挂起,是的话就执行打印,打印完唤起下一个条件。

      public class PrintLog {
/**三种打印类型*/
public static final int TYPE_A = 0;
public static final int TYPE_B = 1;
public static final int TYPE_C = 2;
/**当前类型*/
private int curType = TYPE_A;
    /**对象锁*/
private Lock lock = new ReentrantLock();
/**三个分支条件*/
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();

/**
 * 原理:执行方法前加上锁对象,执行完释放锁。 当前类型一致的话,直接执行,把类型重置为下一个条件,唤醒下一个锁条件;
 * 类型不一样就让条件锁等待。
 */
public void printA() {
lock.lock();
try {
if (curType != TYPE_A) {
// 如果目前是非A的线程打印,A的线程要等待
condition1.await();
}else{

System.out.print("A");
curType = TYPE_B ;
//唤醒信号2
condition2.signal();

}
} catch (Exception e) {
}
lock.unlock();
}


public void printB() {
lock.lock();
try {
if (curType!= TYPE_B) {
condition2.await();
}else{

System.out.print("B");
curType = TYPE_C ;
condition3.signal();

}
} catch (Exception e) {
}
lock.unlock();
}


public void printC() {
lock.lock();
try {
if (curType != TYPE_C) {
condition3.await();
}else{

System.out.print("C");
   curType = TYPE_A;
condition1.signal();

}

} catch (Exception e) {
}
lock.unlock();
}


}

  b)创建一个线程对象,负责循环打印特定字母

      public class ThreadPrint extends Thread {

public static final int PRINT_COUNT=5;
/**打印对象*/
private PrintLog printLog ;
/**打印类型*/
private int type = 0;

public ThreadPrint(PrintLog printLog , int type) {
super();
this.type = type ;
this.printLog = printLog;
}


@Override
public void run() {
for (int i = 0; i <10; i++) {
if (type ==PrintLog.TYPE_A) {
printLog.printA();
}else if(type==PrintLog.TYPE_B){
printLog.printB();
}else {
printLog.printC();
}
}
}
}

 c)测试代码

    public class PrintTest {


public static void main(String[] args) {
PrintLog printLog = new PrintLog() ;
Thread threadA = new ThreadPrint(printLog, PrintLog.TYPE_A);
Thread threadB = new ThreadPrint(printLog, PrintLog.TYPE_B);
Thread threadC = new ThreadPrint(printLog, PrintLog.TYPE_C);
threadA.start();
threadB.start();
threadC.start();
}
}