多線程交替順序執(zhí)行
1.知識(shí)補(bǔ)充
1.1Condition 控制線程通信
Condition 接口描述了可能會(huì)與鎖有關(guān)聯(lián)的條件變量。這些變量在用法上與使用Object.wait 訪問的隱式監(jiān)視器類似,但提供了更強(qiáng)大的功能。需要特別指出的是,單個(gè)Lock 可能與多個(gè)Condition 對(duì)象關(guān)聯(lián)。為了避免兼容性問題,Condition 方法的名稱與對(duì)應(yīng)的Object 版本中的不同。
.在Condition 對(duì)象中,與wait、notify 和notifyAll 方法對(duì)應(yīng)的分別是await、signal 和signalAll。
.Condition 實(shí)例實(shí)質(zhì)上被綁定到一個(gè)鎖上。要為特定Lock 實(shí)例獲得Condition 實(shí)例,請(qǐng)使用其newCondition() 方法。
1.2面試題
編寫一個(gè)程序,開啟3 個(gè)線程,這三個(gè)線程的ID 分別為A、B、C,每個(gè)線程將自己的ID 在屏幕上打印10 遍,要求輸出的結(jié)果必須按順序顯示。
如:ABCABCABC…… 依次遞歸
1.3解決方法
在這里,我們需要使用到上面的condition對(duì)進(jìn)程進(jìn)行控制,使其交替順序執(zhí)行
2.代碼實(shí)現(xiàn)
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author juntech
* @version ${version}
* @date 2019/12/19 16:03
* @ClassName 類名
* @Descripe 描述
*/
public class TestABCAlternateDemo {
public static void main(String[] args) {
ABCAlterNate ad = new ABCAlterNate();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i < 20; i++) {
ad.loopA(i);
}
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i < 20; i++) {
ad.loopB(i);
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i < 20; i++) {
ad.loopC(i);
System.out.println("----------------------------");
}
}
}, "C").start();
}
}
class ABCAlterNate {
private int num = 1; //正在執(zhí)行的標(biāo)志
private Lock lock = new ReentrantLock();
//開啟3個(gè)condition通信
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
/**
* @param totalLoop 循環(huán)次數(shù)
*/
public void loopB(int totalLoop) {
//加鎖
lock.lock();
try {
//1.判斷
if (num != 2) {
conditionB.await();
}
//2.循環(huán)打印
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
}
//3.喚醒
num = 3;
conditionC.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopC(int totalLoop) {
//加鎖
lock.lock();
try {
//1.判斷
if (num != 3) {
conditionC.await();
}
//2.循環(huán)打印
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
}
//3.喚醒
num = 1;
conditionA.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopA(int totalLoop) {
//加鎖
lock.lock();
try {
//1.判斷
if (num != 1) {
conditionA.await();
}
//2.循環(huán)打印
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
}
//3.喚醒
num = 2;
conditionB.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
運(yùn)行,控制臺(tái)輸出:
A 0 1
A 1 1
A 2 1
A 3 1
A 4 1
B 0 1
B 1 1
B 2 1
B 3 1
B 4 1
C 0 1
C 1 1
C 2 1
C 3 1
C 4 1
C 5 1
C 6 1
C 7 1
C 8 1
C 9 1
C 10 1
C 11 1
C 12 1
C 13 1
C 14 1
C 15 1
C 16 1
C 17 1
C 18 1
C 19 1
----------------------------
A 0 2
A 1 2
A 2 2
A 3 2
A 4 2
B 0 2
B 1 2
B 2 2
B 3 2
B 4 2
C 0 2
C 1 2
C 2 2
C 3 2
C 4 2
C 5 2
C 6 2
C 7 2
C 8 2
C 9 2
C 10 2
C 11 2
C 12 2
C 13 2
C 14 2
C 15 2
C 16 2
C 17 2
C 18 2
C 19 2
----------------------------
A 0 3
A 1 3
A 2 3
A 3 3
A 4 3
B 0 3
B 1 3
B 2 3
B 3 3
B 4 3
C 0 3
C 1 3
C 2 3
C 3 3
C 4 3
C 5 3
C 6 3
C 7 3
C 8 3
C 9 3
C 10 3
C 11 3
C 12 3
C 13 3
C 14 3
C 15 3
C 16 3
C 17 3
C 18 3
C 19 3
----------------------------
A 0 4
.....
3.致謝
感謝各位coder抽出寶貴的時(shí)間來(lái)觀看這篇文章!更多詳情請(qǐng)?jiān)L問:juntech