Java 多線程有序執(zhí)行的幾種方法總結(jié)
Java 多線程有序執(zhí)行的幾種方法總結(jié)
同事無(wú)意間提出了這個(gè)問(wèn)題,親自實(shí)踐了兩種方法。當(dāng)然肯定還會(huì)有更多更好的方法。
方法一
import java.util.concurrent.atomic.AtomicInteger;
public class OrderedThread1 {
static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Task task1 = new Task(count, 0);
Task task2 = new Task(count, 1);
Task task3 = new Task(count, 2);
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
Thread thread3 = new Thread(task3);
thread1.setDaemon(true);
thread2.setDaemon(true);
thread3.setDaemon(true);
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1 * 1000);
}
}
class Task implements Runnable {
private AtomicInteger count;
private int order;
public Task(AtomicInteger count, int order) {
this.count = count;
this.order = order;
}
@Override
public void run() {
while (true) {
if (count.get() % 3 == order) {
System.out.println(Thread.currentThread().getName() + " ===== "+ order);
count.incrementAndGet();
}
}
}
}
這種方法應(yīng)該是比較常見(jiàn)的解決方案。利用原子遞增控制線程準(zhǔn)入順序。
方法二
public class OrderedThread2 {
static Holder holder = new Holder();
public static void main(String[] args) throws InterruptedException {
Task1 task1 = new Task1(holder, 0);
Task1 task2 = new Task1(holder, 1);
Task1 task3 = new Task1(holder, 2);
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
Thread thread3 = new Thread(task3);
thread1.setDaemon(true);
thread2.setDaemon(true);
thread3.setDaemon(true);
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1 * 1000);
}
}
class Task1 implements Runnable {
Holder holder;
int order;
public Task1(Holder holder, int order) {
this.holder = holder;
this.order = order;
}
@Override
public void run() {
while (true) {
if (holder.count % 3 == order) {
System.out.println(Thread.currentThread().getName() + " ===== "+ order);
holder.count ++;
}
}
// int i = 0;
// while(i ++ < 10000){
// holder.count ++;
// }
}
}
class Holder {
volatile int count = 0;
}
方法二使用了volatile關(guān)鍵字。讓每個(gè)線程都能拿到最新的count的值,當(dāng)其中一個(gè)線程執(zhí)行++操作后,其他兩個(gè)線程就會(huì)拿到最新的值,并檢查是否符合準(zhǔn)入條件。
ps:volatile不是線程安全的。而且兩者沒(méi)有任何關(guān)系。volatile變量不在用戶線程保存副本,因此對(duì)所有線程都能提供最新的值。但試想,如果多個(gè)線程同時(shí)并發(fā)更新這個(gè)變量,其結(jié)果也是顯而易見(jiàn)的,最后一次的更新會(huì)覆蓋前面所有更新,導(dǎo)致線程不安全。在方法二中,一次只有一個(gè)線程滿足準(zhǔn)入條件,因此不存在對(duì)變量的并發(fā)更新。volatile的值是最新的與線程安全完全是不相干的,所以不要誤用volatile實(shí)現(xiàn)并發(fā)控制。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Nacos框架服務(wù)注冊(cè)實(shí)現(xiàn)流程
這篇文章主要介紹了SpringCloud服務(wù)注冊(cè)之nacos實(shí)現(xiàn)過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
Spring JPA聯(lián)表查詢之OneToOne源碼詳解
這篇文章主要為大家介紹了Spring JPA聯(lián)表查詢之OneToOne源碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案
這篇文章主要介紹了idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Spring Security基于JWT登錄認(rèn)證的項(xiàng)目實(shí)踐
JWT被用來(lái)在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,本文主要介紹了Spring Security基于JWT登錄認(rèn)證的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
SpringBoot統(tǒng)一接口返回及全局異常處理高級(jí)用法
這篇文章主要為大家介紹了SpringBoot統(tǒng)一接口返回及全局異常處理高級(jí)用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Javaweb使用cors完成跨域ajax數(shù)據(jù)交互
本文由跨域、cors的概念開(kāi)始,進(jìn)而向大家介紹了Javaweb使用cors完成跨域ajax數(shù)據(jù)交互的相關(guān)內(nèi)容,需要的朋友可以了解下。2017-09-09
解決若依pageHelper在動(dòng)態(tài)切換數(shù)據(jù)源問(wèn)題
這篇文章主要介紹了解決pageHelper在動(dòng)態(tài)切換數(shù)據(jù)源問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

