使用Condition + Lock 進行實現
private static int count_print = 1;
(1)此處只能用static,來實現每打印一個字符,下一個字符長度加一,static是使該變量只有一個副本,任何改變都是對這個副本的內容做操作
(2)若是想實現每打印一組,下一組字符每個字符長度加一,就不使用static,因為三個線程,有三個線程實例即ThreadTest實例,若不設置成靜態,
那么每次改變的是對象內部的count_print屬性,所以其他兩個線程是不可見的
程序一:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ThreadTest implements Runnable { public static final int COUNT = 5; private final ReentrantLock reentrantLock; private final Condition thisCondition; private final Condition nextCondition; private final char printChar; // 此處只能用static,來實現每打印一個字符,下一個字符長度加一,static是使該變量只有一個副本,任何改變都是對這個副本的內容做操作 // 若是想實現每打印一組,下一組字符每個字符長度加一,就不使用static,因為三個線程,有三個線程實例即ThreadTest實例,若不設置成靜態, // 那么每次改變的是對象內部的count_print屬性,所以其他兩個線程是不可見的 private static int count_print = 1; public ThreadTest(ReentrantLock reentrantLock, Condition thisCondition, Condition nextCondition, char printChar) { this.reentrantLock = reentrantLock; this.thisCondition = thisCondition; this.nextCondition = nextCondition; this.printChar = printChar; } @Override public void run() { reentrantLock.lock(); try { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < count_print; j++) { System.out.print(printChar); } count_print += 1; nextCondition.signal(); // 不是最后一次則通過thisCondtion等待被喚醒 // 必須要加判斷,不然雖然能夠打印5次,但5次后就會直接死鎖 if (i < COUNT - 1) { try { // 使用Condition的await()方法將當前線程放入等待隊列,並使其能在下一次被喚醒繼續往下執行,而不是從頭開始執行 thisCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } } finally { reentrantLock.unlock(); } } public static void main(String args[]) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition(); Thread threadA = new Thread(new ThreadTest(lock, conditionA, conditionB, 'A')); Thread threadB = new Thread(new ThreadTest(lock, conditionB, conditionC, 'B')); Thread threadC = new Thread(new ThreadTest(lock, conditionC, conditionA, 'C')); threadA.start(); Thread.sleep(100); threadB.start(); Thread.sleep(100); threadC.start(); } }
(1)//此處只能用static,來實現每打印一個字符,下一個字符長度加一,static是使該變量只有一個副本,任何改變都是對這個副本的內容做操作
private static int count_print = 1;
輸出結果:
(2)若是想實現每打印一組,下一組字符每個字符長度加一,就不使用static,因為三個線程,有三個線程實例即ThreadTest實例,若不設置成靜態,
那么每次改變的是對象內部的count_print屬性,所以其他兩個線程是不可見的,可能不太好理解,將ThreadTest類單獨寫出來,在利用import引入進另一個有主方法的類就比較直觀了
private int count_print = 1;
輸出結果:
程序二
//只是循環打印每組字符,不考慮字符增長 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ThreadTest implements Runnable { public static final int COUNT = 5; private final ReentrantLock reentrantLock; private final Condition thisCondition; private final Condition nextCondition; private final char printChar; private static int count_print = 1; public ThreadTest(ReentrantLock reentrantLock, Condition thisCondition, Condition nextCondition, char printChar) { this.reentrantLock = reentrantLock; this.thisCondition = thisCondition; this.nextCondition = nextCondition; this.printChar = printChar; } @Override public void run() { reentrantLock.lock(); try { for (int i = 0; i < COUNT; i++) { System.out.print(printChar); nextCondition.signal(); if (i < COUNT - 1) { try { // 使用Condition的await()方法將當前線程放入等待隊列,並使其能在下一次被喚醒繼續往下執行,而不是從頭開始執行 thisCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } } finally { reentrantLock.unlock(); } } public static void main(String args[]) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition(); Thread threadA = new Thread(new ThreadTest(lock, conditionA, conditionB, 'A')); Thread threadB = new Thread(new ThreadTest(lock, conditionB, conditionC, 'B')); Thread threadC = new Thread(new ThreadTest(lock, conditionC, conditionA, 'C')); threadA.start(); Thread.sleep(100); threadB.start(); Thread.sleep(100); threadC.start(); } }
運行結果為: