举例, 如果交替打印,到100 就停止, 也就是 从1~100 线程A ,线程B ,线程 B 交替打印。
ok,代码稍作调整 :
加上2个值
一个是打印的数字,这个会一直 +1 输出;
一个是用于线程循环的,之前是while(true)
,这样会一直跑。
如果 终止标记还是false,就继续执行:
每个打印方法都加上判断和累计+1的代码:
看看效果:
整体代码贴一下:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.Condition; public class DoTest { //控制三个线程 ABC,保证同一时刻只有一个线程工作 private static Lock lock = new ReentrantLock(true); // Condition ,控制等待或是 通知 private static Condition conditionA = lock.newCondition(); private static Condition conditionB = lock.newCondition(); private static Condition conditionC = lock.newCondition(); //默认的通知 暗号 A private static String CODE = "A"; //设置初始打印值 private static int COUNT_NUM = 1; //线程是否需要终止 标记 private static volatile boolean IS_INTERRUPT = false; public static void main(String[] args) { Thread A = new Thread(() -> { while (!IS_INTERRUPT) { try { printA(); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread B = new Thread(() -> { while (!IS_INTERRUPT) { try { printB(); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread C = new Thread(() -> { while (!IS_INTERRUPT) { try { printC(); } catch (InterruptedException e) { e.printStackTrace(); } } }); A.start(); B.start(); C.start(); } public static void printA() throws InterruptedException { //等待 lock.lock(); try { if (COUNT_NUM >= 100) { IS_INTERRUPT = true; return; } //核对 while (!CODE.equals("A")) { //暗号不对,就进入等待 conditionA.await(); } System.out.println("A, count" + COUNT_NUM); //改暗号,通知B CODE = "B"; COUNT_NUM = COUNT_NUM + 1; conditionB.signalAll(); } finally { lock.unlock(); } } public static void printB() throws InterruptedException { lock.lock(); try { if (COUNT_NUM >= 100) { IS_INTERRUPT = true; return; } while (!CODE.equals("B")) { conditionB.await(); } System.out.println("B, count" + COUNT_NUM); //改暗号,通知C CODE = "C"; COUNT_NUM = COUNT_NUM + 1; conditionC.signalAll(); } finally { lock.unlock(); } } public static void printC() throws InterruptedException { lock.lock(); try { if (COUNT_NUM >= 100) { IS_INTERRUPT = true; return; } while (!CODE.equals("C")) { conditionC.await(); } System.out.println("C, count" + COUNT_NUM); //改暗号,通知A CODE = "A"; COUNT_NUM = COUNT_NUM + 1; conditionA.signalAll(); } finally { lock.unlock(); } } }
可能看到这里,有些初学者会心有疑惑,因为他没了解过 ReentrantLock、Lock 、Condition ,就觉得这个看了不踏实。
没事的,其实只是为了给大家实打实分析思路, 用synchronized 配合 wait() 和 notifyAll 也是一样的。
notifyAll 大不了就全部通知唤醒,然后自己核对暗号再进入等待。
示例,上代码:
public class DoTest1 { private volatile int COUNT_NUM = 1; private volatile String CODE = "A"; private static int oneTimes = 34; private static int othersTimes = 33; void onePrint() { synchronized (this) { while(!CODE.equals("A")) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + ": " + COUNT_NUM); COUNT_NUM++; CODE = "B"; notifyAll(); } } void twoPrint() { synchronized (this) { while(!CODE.equals("B")) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + ": " + COUNT_NUM); COUNT_NUM++; CODE = "C"; notifyAll(); } } void threePrint() { synchronized (this) { while(!CODE.equals("C")) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + ": " + COUNT_NUM); COUNT_NUM++; CODE = "A"; notifyAll(); } } public static void main(String[] args) { DoTest1 printNumber = new DoTest1(); new Thread(() -> { for (int i = 0; i < oneTimes; i++) { printNumber.onePrint(); } },"线程A").start(); new Thread(() -> { for (int i = 0; i < othersTimes; i++) { printNumber.twoPrint(); } },"线程B").start(); new Thread(() -> { for (int i = 0; i < othersTimes; i++) { printNumber.threePrint(); } },"线程C").start(); } }
代码简析:
看看效果:
好了,该篇就到这吧。