- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- java如何實(shí)現多線(xiàn)程的順序執行
編寫(xiě)一個(gè)程序,啟動(dòng)三個(gè)線(xiàn)程,三個(gè)線(xiàn)程的name分別是A,B,C;,每個(gè)線(xiàn)程將自己的ID值在屏幕上打印5遍,打印順序是ABCABC...
public class MyService { private int flag = 1; public synchronized void printA(){ while (flag != 1) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); flag = 2; this.notifyAll(); } public synchronized void printB(){ while (flag != 2) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); flag = 3; this.notifyAll(); } public synchronized void printC(){ while (flag != 3) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); flag = 1; this.notifyAll(); } }
這里的判斷條件中用的是 while 而不是 if , 這兩者之間有什么區別呢? 線(xiàn)程從 wait 狀態(tài)被喚醒,并且獲得鎖以后會(huì )繼續往下執行,比如 A 調用nofityAll() 喚醒 B,C,這時(shí) B與C誰(shuí)會(huì )先獲得鎖是不確定的。如果是C先獲得了鎖,那么C就繼續往下執行打印,這與我們的期望的不符。所以這里我們使用了一個(gè) while,當C獲得鎖以后再去判斷一下flag,如果這時(shí)還不是它執行的時(shí)候,它就再次進(jìn)入wait狀態(tài)。此時(shí)A與C都是wait狀態(tài),獲得鎖的一定是B,從而實(shí)現我們期望的順序打印。
package testABC; public class TestMain { public static void main(String[] args) { //編寫(xiě)一個(gè)程序,啟動(dòng)三個(gè)線(xiàn)程,三個(gè)線(xiàn)程的ID分別是A,B,C;,每個(gè)線(xiàn)程將自己的ID值在屏幕上打印5遍,打印順序是ABCABC... // MyService service = new MyService(); MyService2 service = new MyService2(); Thread A = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { service.printA(); } } }); A.setName("A"); Thread B = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { service.printB(); } } }); B.setName("B"); Thread C = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { service.printC(); } } }); C.setName("C"); A.start(); B.start(); C.start(); } }
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class MyService2 { private int flag = 1; private Lock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); private Condition conditionC = lock.newCondition(); public void printA() { try { lock.lock(); if (flag != 1) { try { conditionA.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); flag = 2; conditionB.signal(); } finally { lock.unlock(); } } public void printB() { try { lock.lock(); if (flag != 2) { try { conditionB.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); flag = 3; conditionC.signal(); } finally { lock.unlock(); } } public void printC() { try { lock.lock(); if (flag != 3) { try { conditionC.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); flag = 1; conditionA.signal(); } finally { lock.unlock(); } } }
當使用LOCK時(shí)可以不使用while因為condition可以喚醒指定的線(xiàn)程。同時(shí)注意必須先調用 conditionA.signal(); 再調用 lock.unlock(); ,否則會(huì )拋 java.lang.IllegalMonitorStateException 異常。因為在調用unlock之后,當前線(xiàn)程已不是此監視器對象condition的持有者。也就是說(shuō)要在此線(xiàn)程持有鎖定對象時(shí),才能使用此鎖定對象。
api中的解釋
public class IllegalMonitorStateExceptionextends RuntimeException
拋出的異常表明某一線(xiàn)程已經(jīng)試圖等待對象的監視器,或者試圖通知其他正在等待對象的監視器而本身沒(méi)有指定監視器的線(xiàn)程。
從以下版本開(kāi)始:
JDK1.0
另請參見(jiàn):
Object.notify(), Object.notifyAll(), Object.wait(), Object.wait(long), Object.wait(long, int), 序列化表格
也就是當前的線(xiàn)程不是此對象監視器的所有者。也就是要在當前線(xiàn)程鎖定對象,才能用鎖定的對象此行這些方法,需要用到synchronized ,鎖定什么對象就用什么對象來(lái)執行
notify(), notifyAll(),wait(), wait(long), wait(long, int)操作,否則就會(huì )報IllegalMonitorStateException異常。
例如 :
exapmle 1,鎖定方法所屬的實(shí)例對象:
public synchronized void method(){ //然后就可以調用:this.notify()... //或者直接調用notify()... }
exapmle 2,鎖定方法所屬的實(shí)例的Class:
public Class Test{ public static synchronized void method(){ //然后調用:Test.class.notify()... } }
exapmle 3,鎖定其他對象:
public Class Test{ public Object lock = new Object(); public static void method(){ synchronized (lock) { //需要調用 lock.notify(); } } }
到此這篇關(guān)于java如何實(shí)現多線(xiàn)程的順序執行的文章就介紹到這了,更多相關(guān)java 多線(xiàn)程順序執行內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站