您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Java中怎么實現線程協調運行操作,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
一 點睛
借助于Object類提供的wait()、notify()和notifyAll()三個方法,可實現Java線程協調運行。這三個方法并不屬于Thread類,而是屬于Object類。但這三個方法必須同步監視器對象調用。
關于這三個方法的解釋如下:
wait():導致當前線程等待,直到其他線程調用該同步監視器的notify()方法或notifyAll()方法來喚醒該線程。該wait()方法有三種形式:無時間參數的wait(一直等待,直到其他線程通知),帶毫秒參數的wait和帶毫秒、微秒參數的wait(這兩種方法都是等待指定時間后自動蘇醒)。調用wait()方法的當前線程會釋放對該同步監視器的鎖定。
notify():喚醒在此同步監視器上等待的單個線程。如果所有線程都在此同步監視器上等待,則會選擇喚醒其中一個線程。選擇是任意性的。只有當前線程放棄對該同步監視器的鎖定后(使用wait()方法),才可以執行被喚醒的線程。
notifyAll():喚醒在此同步監視器上等待的所有線程。只有當前線程放棄對該同步監視器的鎖定后,才可以執行被喚醒的線程。
對于使用synchronized修飾的同步方法,因為該類的默認實例(this)就是同步監視器,所以可以直接調用這三個方法。
對于使用synchronized修飾的同步塊,同步監視器是synchronized后括號里的對象,所以必須使用該對象調用這三個方法。
二 實戰
1 Account類
public class Account { // 封裝賬戶編號、賬戶余額的兩個成員變量 private String accountNo; private double balance; // 標識賬戶中是否已有存款的旗標 private boolean flag = false; public Account(){} // 構造器 public Account(String accountNo , double balance) { this.accountNo = accountNo; this.balance = balance; } // accountNo的setter和getter方法 public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public String getAccountNo() { return this.accountNo; } // 因此賬戶余額不允許隨便修改,所以只為balance提供getter方法, public double getBalance() { return this.balance; } public synchronized void draw(double drawAmount) { try { // 如果flag為假,表明賬戶中還沒有人存錢進去,取錢方法阻塞 if (!flag) { wait(); } else { // 執行取錢 System.out.println(Thread.currentThread().getName() + " 取錢:" + drawAmount); balance -= drawAmount; System.out.println("賬戶余額為:" + balance); // 將標識賬戶是否已有存款的旗標設為false。 flag = false; // 喚醒其他線程 notifyAll(); } } catch (InterruptedException ex) { ex.printStackTrace(); } } public synchronized void deposit(double depositAmount) { try { // 如果flag為真,表明賬戶中已有人存錢進去,則存錢方法阻塞 if (flag) //① { wait(); } else { // 執行存款 System.out.println(Thread.currentThread().getName() + " 存款:" + depositAmount); balance += depositAmount; System.out.println("賬戶余額為:" + balance); // 將表示賬戶是否已有存款的旗標設為true flag = true; // 喚醒其他線程 notifyAll(); } } catch (InterruptedException ex) { ex.printStackTrace(); } } // 下面兩個方法根據accountNo來重寫hashCode()和equals()方法 public int hashCode() { return accountNo.hashCode(); } public boolean equals(Object obj) { if(this == obj) return true; if (obj !=null && obj.getClass() == Account.class) { Account target = (Account)obj; return target.getAccountNo().equals(accountNo); } return false; } }
2 DrawThread線程類
public class DrawThread extends Thread { // 模擬用戶賬戶 private Account account; // 當前取錢線程所希望取的錢數 private double drawAmount; public DrawThread(String name , Account account , double drawAmount) { super(name); this.account = account; this.drawAmount = drawAmount; } // 重復100次執行取錢操作 public void run() { for (int i = 0 ; i < 100 ; i++ ) { account.draw(drawAmount); } } }
3 DepositThread線程類
public class DepositThread extends Thread { // 模擬用戶賬戶 private Account account; // 當前取錢線程所希望存款的錢數 private double depositAmount; public DepositThread(String name , Account account , double depositAmount) { super(name); this.account = account; this.depositAmount = depositAmount; } // 重復100次執行存款操作 public void run() { for (int i = 0 ; i < 100 ; i++ ) { account.deposit(depositAmount); } } }
4 測試類
public class DrawTest { public static void main(String[] args) { // 創建一個賬戶 Account acct = new Account("1234567" , 0); new DrawThread("取錢者" , acct , 800).start(); new DepositThread("存款者甲" , acct , 800).start(); new DepositThread("存款者乙" , acct , 800).start(); new DepositThread("存款者丙" , acct , 800).start(); } }
三 運行結果
......
存款者甲 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者丙 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者甲 存款:800.0
賬戶余額為:800.0
以上就是Java中怎么實現線程協調運行操作,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。