Java 多線程有序執(zhí)行的幾種方法總結(jié)
Java 多線程有序執(zhí)行的幾種方法總結(jié)
同事無意間提出了這個(gè)問題,親自實(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)該是比較常見的解決方案。利用原子遞增控制線程準(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不是線程安全的。而且兩者沒有任何關(guān)系。volatile變量不在用戶線程保存副本,因此對(duì)所有線程都能提供最新的值。但試想,如果多個(gè)線程同時(shí)并發(fā)更新這個(gè)變量,其結(jié)果也是顯而易見的,最后一次的更新會(huì)覆蓋前面所有更新,導(dǎo)致線程不安全。在方法二中,一次只有一個(gè)線程滿足準(zhǔn)入條件,因此不存在對(duì)變量的并發(fā)更新。volatile的值是最新的與線程安全完全是不相干的,所以不要誤用volatile實(shí)現(xiàn)并發(fā)控制。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Nacos框架服務(wù)注冊實(shí)現(xiàn)流程
這篇文章主要介紹了SpringCloud服務(wù)注冊之nacos實(shí)現(xiàn)過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Spring JPA聯(lián)表查詢之OneToOne源碼詳解
這篇文章主要為大家介紹了Spring JPA聯(lián)表查詢之OneToOne源碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案
這篇文章主要介紹了idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Spring Security基于JWT登錄認(rèn)證的項(xiàng)目實(shí)踐
JWT被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,本文主要介紹了Spring Security基于JWT登錄認(rèn)證的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07SpringBoot統(tǒng)一接口返回及全局異常處理高級(jí)用法
這篇文章主要為大家介紹了SpringBoot統(tǒng)一接口返回及全局異常處理高級(jí)用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Javaweb使用cors完成跨域ajax數(shù)據(jù)交互
本文由跨域、cors的概念開始,進(jìn)而向大家介紹了Javaweb使用cors完成跨域ajax數(shù)據(jù)交互的相關(guān)內(nèi)容,需要的朋友可以了解下。2017-09-09解決若依pageHelper在動(dòng)態(tài)切換數(shù)據(jù)源問題
這篇文章主要介紹了解決pageHelper在動(dòng)態(tài)切換數(shù)據(jù)源問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01