前两天看Java吧有人求助这个问题。想了想并不是很难。今天就顺手实现了一下。
我自己想到的有两种方法,一个是使用synchronized,一个是使用lock。
一、synchronized
package com.test; public class PrintABC { private static int count = 0; public static void main(String[] args) { String str = "ABC"; PrintABC printABC = new PrintABC(); ThreadA threadA = printABC.new ThreadA(str); ThreadB threadB = printABC.new ThreadB(str); ThreadC threadC = printABC.new ThreadC(str); threadA.start(); threadB.start(); threadC.start(); } /** * 打印A * @author LKB * */ class ThreadA extends Thread{ private String str; public ThreadA(String str) { // TODO Auto-generated constructor stub this.str = str; } public void run(){ while(count < 28){ synchronized (str) { if(count%3 == 0){ System.out.println("A"); count++; } } } } } /** * 打印B * @author LKB * */ class ThreadB extends Thread{ private String str; public ThreadB(String str) { // TODO Auto-generated constructor stub this.str = str; } public void run(){ while(count < 29){ synchronized (str) { if(count%3 == 1){ System.out.println("B"); count++; } } } } } /** * 打印C * @author LKB * */ class ThreadC extends Thread{ private String str; public ThreadC(String str) { // TODO Auto-generated constructor stub this.str = str; } public void run(){ while(count < 30){ synchronized (str) { if(count%3 == 2){ System.out.println("C"); System.out.println("++++++"); System.out.println("------"); count++; } } } } } }
这个方法的关键是synchronized关键字的位置。把它放在while判断之下就OK了。如果把synchronized关键字放在while外,则一直在锁中无法跳出锁。
二、lock
package com.test; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class PrintABC2 { private int count = 0; private Lock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); private Condition conditionC = lock.newCondition(); public static void main(String[] args) { PrintABC2 printABC = new PrintABC2(); ThreadA threadA = printABC.new ThreadA(); ThreadB threadB = printABC.new ThreadB(); ThreadC threadC = printABC.new ThreadC(); threadA.start(); threadB.start(); threadC.start(); } /** * 打印A * @author LKB * */ class ThreadA extends Thread{ public void run(){ try { lock.lock(); while(count < 30){ if (count%3 != 0) { conditionA.await(); } System.out.println("A"); count ++; conditionB.signalAll(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { lock.unlock(); System.out.println("ThreadA 中执行了 unlock"); } } } /** * 打印B * @author LKB * */ class ThreadB extends Thread{ public void run(){ try { lock.lock(); while(count < 30){ if (count%3 != 1) { conditionB.await(); } System.out.println("B"); count ++; conditionC.signalAll(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { lock.unlock(); System.out.println("ThreadB 中执行了 unlock"); } } } /** * 打印C * @author LKB * */ class ThreadC extends Thread{ public void run(){ try { lock.lock(); while(count < 30){ if (count%3 != 2) { conditionC.await(); } System.out.println("C"); System.out.println("+++++++"); System.out.println("-------"); count ++; if(count < 30){ conditionA.signalAll(); } } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { lock.unlock(); System.out.println("ThreadC 中执行了 unlock"); } } } }
lock方法相对而言就简单多了,不需要精妙地设计,只需要知道lock和condition的用法就好了。
在一个lock对象里可以创建多个Condition(即对象监视器)实例。线程对象可以注册到指定的Condition中,从而可以有选择性地进行线程通知。