激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java使用wait() notify()方法操作共享資源詳解

Java使用wait() notify()方法操作共享資源詳解

2021-01-16 10:57溪山晴雪 Java教程

這篇文章主要為大家詳細介紹了Java使用wait() notify()方法操作共享資源,具有一定的參考價值,感興趣的小伙伴們可以參考一下

Java多個線程共享資源;

  1)wait()、notify()和notifyAll()方法是本地方法,并且為final方法,無法被重寫。

  2)調用某個對象的wait()方法能讓當前線程阻塞,并且當前線程必須擁有此對象的monitor(即鎖,或者叫管程)

  3)調用某個對象的notify()方法能夠喚醒一個正在等待這個對象的monitor的線程,如果有多個線程都在等待這個對象的monitor,則只能喚醒其中一個線程;

  4)調用notifyAll()方法能夠喚醒所有正在等待這個對象的monitor的線程; 

        在Java中,是沒有類似于PV操作、進程互斥等相關的方法的。JAVA的進程同步是通過synchronized()來實現的,需要說明的是,Java的synchronized()方法類似于操作系統概念中的互斥內存塊,在Java中的Object類對象中,都是帶有一個內存鎖的,在有線程獲取該內存鎖后,其它線程無法訪問該內存,從而實現Java中簡單的同步、互斥操作。明白這個原理,就能理解為什么synchronized(this)與synchronized(static XXX)的區別了,synchronized就是針對內存區塊申請內存鎖,this關鍵字代表類的一個對象,所以其內存鎖是針對相同對象的互斥操作,而static成員屬于類專有,其內存空間為該類所有成員共有,這就導致synchronized()對static成員加鎖,相當于對類加鎖,也就是在該類的所有成員間實現互斥,在同一時間只有一個線程可訪問該類的實例。如果需要在線程間相互喚醒就需要借助Object類的wait()方法及nofity()方法。

說了這么一堆,可能似懂非懂,那么接下來用一個例子來說明問題,用多線程實現連續的1,2,1,2,1,2,1,2,1,2輸出。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.study.thread;
/**
 * 多線程
 * @ClassName: PrintFile
 * @date 2017年10月10日 下午4:05:04
 */
public class PrintFile implements Runnable{
  //當前線程id
  private int id ;
  //共享資源
  public byte[] res ;
  
  //如果類里寫了有參構造器,而任然想保留無參數構造方法,則必須顯式的寫出該方法。
  public PrintFile() {
    super();
//    System.out.println("我是構造器");
  }
 
  public PrintFile(int id, byte[] res) {
    //構造器中使用super()/this(),必須放在第一行。
    this();
    this.id = id;
    this.res = res;
  }
 
  //靜態計數器
  public static int count = 5;
  
  @Override
  public void run() {
    synchronized (res) {
      while(count-->=0){
        try {
          res.notify();//喚醒其他線程中的某一個(喚醒等待res的其他線程,當前線程執行完后要釋放鎖)
          System.out.println("當前線程id值:"+id);
          
          res.wait();//當前線程阻塞,等待被喚醒
          System.out.println("現在執行的線程是"+Thread.currentThread().getName()+",--wait()后的代碼繼續執行:"+id);
          
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      return;
    }
  }
}

測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.study.thread;
 
public class PrintFileTest {
 public static void main(String[] args) {
  byte[] res = new byte[]{0,1,2};//共享資源
  PrintFile p1 = new PrintFile(1, res);
  PrintFile p2 = new PrintFile(2, res);
  
  Thread t1 = new Thread(p1, "a");
  Thread t2 = new Thread(p2, "b");
    
  t1.start();
  t2.start();
 }
}

結果:

當前線程id值:1
當前線程id值:2
現在執行的線程是a,--wait()后的代碼繼續執行:1
當前線程id值:1
現在執行的線程是b,--wait()后的代碼繼續執行:2
當前線程id值:2
現在執行的線程是a,--wait()后的代碼繼續執行:1
當前線程id值:1
現在執行的線程是b,--wait()后的代碼繼續執行:2
當前線程id值:2
現在執行的線程是a,--wait()后的代碼繼續執行:1

下面解釋為什么會出現這樣的結果:

首先1、2號線程啟動,這里假設1號線程先運行run方法獲得資源(實際上是不確定的),獲得對象a的鎖,進入while循環(用于控制輸出幾輪):

1、此時對象調用它的喚醒方法notify(),意思是這個同步塊執行完后它要釋放鎖,把鎖交給等待a資源的線程;

2、輸出1;

3、該對象執行等待方法,意思是此時此刻起擁有這個對象鎖的線程(也就是這里的1號線程)釋放CPU控制權,釋放鎖,并且線程進入阻塞狀態,后面的代碼暫時不執行,因未執行完同步塊,所以1也沒起作用;

4、在這之前的某時刻線程2運行run方法,但苦于沒有獲得a對象的鎖,所以無法繼續運行,但3步驟之后,它獲得了a的鎖,此時執行a的喚醒方法notify(),同理,意思是這個同步塊執行完后它要釋放鎖,把鎖交給等待a資源的線程;

5、輸出2;

6、執行a的等待方法,意思是此時此刻起擁有這個對象鎖的線程(也就是這里的2號線程)釋放CPU控制權,釋放鎖,并且線程進入阻塞狀態,后面的代碼暫時不執行,因未執行完同步塊,所以2號線程的4步驟的喚醒方法也沒起作用;

7、此時1號線程執行到3步驟,發現對象鎖沒有被使用,所以繼續執行3步驟中wait方法后面的代碼,于是輸出:------線程1獲得鎖,wait()后的代碼繼續運行:1;

8、此時while循環滿足條件,繼續執行,所以,再執行1號線程的喚醒方法,意思是這個同步塊執行完后它要釋放鎖;

9、輸出1;

10、執行等待方法,線程1阻塞,釋放資源鎖;

11、此時線程2又獲得了鎖,執行到步驟6,繼續執行wait方法后面的代碼,所以輸出:------線程2獲得鎖,wait()后的代碼繼續運行:2;

12、繼續執行while循環,輸出2;

··· ···

通過上述步驟,相信大家已經明白這兩個方法的使用了,但該程序還存在一個問題,當while循環不滿足條件時,肯定會有線程還在等待資源,所以主線程一直不會終止。當然這個程序的目的僅僅為了給大家演示這兩個方法怎么用。

總結:

 wait()方法與notify()必須要與synchronized(resource)一起使用。也就是wait與notify針對已經獲取了resource鎖的線程進行操作,從語法角度來說就是Obj.wait(),Obj.notify必須在synchronized(Obj){...}語句塊內。從功能上來說wait()線程在獲取對象鎖后,主動釋放CPU控制權,主動釋放對象鎖,同時本線程休眠。直到有其它線程調用對象的notify()喚醒該線程,才能繼續獲取對象鎖,并繼續執行。相應的notify()就是對對象鎖的釋放操作?!疽虼?,我們可以發現,wait和notify方法均可釋放對象的鎖,但wait同時釋放CPU控制權,即它后面的代碼停止執行,線程進入阻塞狀態,而notify方法不立刻釋放CPU控制權,而是在相應的synchronized(){}語句塊執行結束,再自動釋放鎖?!酷尫沛i后,JVM會在等待resoure的線程中選取一線程,賦予其對象鎖,喚醒線程,繼續執行。這樣就提供了在線程間同步、喚醒的操作。Thread.sleep()與Object.wait()二者都可以暫停當前線程,釋放CPU控制權,主要的區別在于Object.wait()在釋放CPU同時,釋放了對象鎖的控制,而在同步塊中的Thread.sleep()方法并不釋放鎖,僅釋放CPU控制權。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/tashaxing/p/7646215.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩精品网站在线观看 | 亚洲成人在线视频网 | 国产精品午夜一区 | 黄色片免费在线 | 日韩午夜片| 国产在线精品一区二区夜色 | 亚洲电影在线观看高清免费 | 色淫湿视频| 天天操天天看 | 成人午夜视频免费 | 国内精品视频饥渴少妇在线播放 | 免费看黄色一级片 | 艹逼视频污 | qyl在线视频精品免费观看 | 久久蜜桃精品一区二区三区综合网 | 久久久久北条麻妃免费看 | 成人精品免费看 | 国产免费让你躁在线视频 | 亚洲自拍第一 | 国产男女爽爽爽爽爽免费视频 | 日韩av在线网址 | 韩国草草影院 | 欧洲成人综合网 | 久久精品观看 | 欧美黄 片免费观看 | 精品一区二区三区毛片 | 国产精品一区二区三区在线播放 | 在线成人免费观看视频 | 久久久久女人精品毛片九一 | 啪啪激情 | 久久狠狠高潮亚洲精品 | 中文字幕视频在线播放 | 欧美3p激情一区二区三区猛视频 | 激情久久一区二区 | 91午夜少妇三级全黄 | 精品视频一区二区三区四区 | 亚洲第一成人久久网站 | 国产美女视频黄a视频免费 日韩黄色在线播放 | 狠狠操夜夜爱 | 青青操国产 | 91久久99热青草国产 |