java多線程實現(xiàn)有序輸出ABC
3個線程,線程1輸出A,線程2輸出B,線程3輸出C,讓這個3個線程循環(huán)有序地輸出ABCABC…
看到這個題目,感覺很有意思,問題的本質是在多線程執(zhí)行環(huán)境,控制線程的執(zhí)行順序,實現(xiàn)的方式有非常多種,本質上需要解決Java多線程環(huán)境下的線程執(zhí)行的同步和利用鎖機制來控制線程的執(zhí)行順序。
方式1:利用synchronized
這種方式也就是使用java內置的monitor機制,配合wait和notifyAll,代碼如下:
(1)利用volatile做線程間資源的同步訪問,同時作為線程調度的標志;
(2)利用notifyAll來喚醒其他等待當前的monitor資源的線程;
public class ThreadOrderWithSync {
private volatile int flag = 'A';
private final static Object LOCK = new Object();
Runnable a = () -> {
while (true) {
synchronized (LOCK) {
if (flag == 'A' ) {
System.out.println("A");
flag = 'B';
// let other thread race to get the monitor
LOCK.notifyAll();
} else {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Runnable b = () -> {
while (true) {
synchronized (LOCK) {
if (flag == 'B' ) {
System.out.println("B");
flag = 'C';
// let other thread race to get the monitor
LOCK.notifyAll();
} else {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Runnable c = () -> {
while (true) {
synchronized (LOCK) {
if (flag == 'C' ) {
System.out.println("C");
flag = 'A';
// let other thread race to get the monitor
LOCK.notifyAll();
} else {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
public void runTest() {
Thread ta = new Thread(a);
Thread tb = new Thread(b);
Thread tc = new Thread(c);
ta.start();
tb.start();
tc.start();
}
public static void main(String[] args) {
ThreadOrderWithSync sync = new ThreadOrderWithSync();
sync.runTest();
}
}
方式2:利用并發(fā)包ReentrantLock和Condition的鎖機制
上面方式1的synchronized機制,因為當前的所有線程都爭用同一個monitor資源,因此只能通過notifyAll來通知其他線程來加鎖,因此每次都會出現(xiàn)race condition,但是,通過ReentrantLock的Condition,我們可以精確控制,下一個該喚醒signal的線程是哪一個(因為我們知道執(zhí)行的順序是A->B->C的循環(huán)),相比synchronized的機制,Condition機制可以更精細化線程的調度設計,代碼示例如下:
/**
* @author xijin.zeng created on 2018/8/31
* Thrads runing order: A->B->C
*/
public class ThreadOrderWithCondition {
private static final ReentrantLock LOCK = new ReentrantLock();
private static final Condition C_A = LOCK.newCondition();
private static final Condition C_B = LOCK.newCondition();
private static final Condition C_C = LOCK.newCondition();
/**
* init for A to run first
*/
private volatile int flag = 'A';
Runnable a = () -> {
while (true) {
LOCK.lock();
if (flag == 'A') {
System.out.println("A");
flag = 'B';
// signal B to run
C_B.signal();
} else {
try {
// block and wait signal to invoke
C_A.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
LOCK.unlock();
}
};
Runnable b = () -> {
while (true) {
LOCK.lock();
if (flag == 'B') {
System.out.println("B");
flag = 'C';
// signal C to run
C_C.signal();
} else {
try {
// block and wait signal to invoke
C_B.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
LOCK.unlock();
}
};
Runnable c = () -> {
while (true) {
LOCK.lock();
if (flag == 'C') {
System.out.println("C");
flag = 'A';
// signal A to run
C_A.signal();
} else {
try {
// block and wait signal to invoke
C_C.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
LOCK.unlock();
}
};
public void runTest() {
Thread threadA = new Thread(a);
Thread threadB = new Thread(b);
Thread threadC = new Thread(c);
threadA.start();
threadB.start();
threadC.start();
}
public static void main(String[] args) {
ThreadOrderWithCondition o = new ThreadOrderWithCondition();
o.runTest();
}
}
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
圖數(shù)據(jù)庫NebulaGraph的Java 數(shù)據(jù)解析實踐與指導詳解
這篇文章主要介紹了圖數(shù)據(jù)庫NebulaGraph的Java 數(shù)據(jù)解析實踐與指導詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04
Springboot+SpringSecurity+JWT實現(xiàn)用戶登錄和權限認證示例
這篇文章主要介紹了Springboot+SpringSecurity+JWT實現(xiàn)用戶登錄和權限認證示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06
Spring Cloud Zuul自定義過濾器的實現(xiàn)
這篇文章主要介紹了自定義Spring Cloud Zuul過濾器的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03

