天天看點

黑馬程式員 Java多線程

------- android教育訓練、java教育訓練、期待與您交流! ----------

1,可以使用靜态方法Thread.currentTread().getName()來擷取目前線程的線程名

2,如果我們對某個線程對象在啟動之前調用了setDaemon(true)方法,這個線程就變成了背景線程,對JAVA程式來說,隻要還有一個前台線程在運作,這個程序就不會結束,如果一個程序中隻有背景線程運作,這個程序就會結束,setDaemon方法首先調用該線程的checkAccess方法,且不帶任何參數。這可能抛出 SecurityException(在目前線程中)如果訓示線程沒有處于請求操作所要求的适當狀态還會抛出IllegalThreadStateException異常

注:

checkAccess public final void checkAccess()判定目前運作的線程是否有權修改該線程。如果有安全管理器,則調用其 checkAccess方法,并将該線程作為其參數。這可能導緻抛出 SecurityException -如果不允許目前線程通路該線程

3,線程A調用線程B的join()方法後,線程A就會等線程B結束後才繼續運作,join()等待該線程終止,join(long millis)等待該線程終止的時間最長為 millis毫秒。join(long millis,int nanos)等待該線程終止的時間最長為 millis毫秒 + nanos 納秒。

注:

join

public final void join(long millis,  int nanos) throwsInterruptedException等待該線程終止的時間最長為 millis毫秒 + nanos 納秒。

參數:

millis - 以毫秒為機關的等待時間。

nanos - 要等待的 0-999999附加納秒。 

抛出: 

IllegalArgumentException - 如果 millis值為負,則 nanos的值不在 0-999999範圍内。 

InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态被清除。

public final void join()  throwsInterruptedException等待該線程終止。

抛出: 

InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态被清除。

public final void join(long millis) throws InterruptedException等待該線程終止的時間最長為 millis毫秒。逾時為 0 意味着要一直等下去。

參數:

millis - 以毫秒為機關的等待時間。 

抛出: 

InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态被清除。

4,建立多線程有兩種方式,一種是繼承Thread類,另一種是實作Runnable接口,我覺得如果能使用接口就選擇接口,因為這确實能很好地展現出面向對象的設計思想

5,sleep

public static void sleep(long millis) throws InterruptedException在指定的毫秒數内讓目前正在執行的線程休眠(暫停執行),此操作受到系統計時器和排程程式精度和準确性的影響。該線程不丢失任何螢幕的所屬權。

參數:

millis - 以毫秒為機關的休眠時間。 

抛出: 

InterruptedException - 如果任何線程中斷了目前線程。當抛出該異常時,目前線程的中斷狀态被清除。

6,當線上程A中啟動了線程B後,CPU不一定立刻跳轉到線程B,它很可能要再線上程A中執行一會兒了再跳轉到線程B,為了讓CPU立刻跳轉到線程B,我們可以在啟到了線程B後線上程A中調用Tread類中的sleep方法讓線程A等待一會兒

7,synchronized的四種用法:

(1)方法聲明時使用,放在範圍操作符(public等)之後,傳回類型聲明(void等)之前,即一次隻能有一個線程進入該方法,其他線程想在此時調用該方法,隻能排隊等候,目前線程(就是在synchronized方法内部的線程)執行完該方法後,别的線程才能進入。

(2)對某一代碼塊使用,synchronized後跟括号,括号裡是變量,這樣一次隻有一個線程進入該代碼塊。

(3)synchronized後面括号裡是一對象,如果線程進入,則得到對象鎖,那麼别的線程在該類所有對象上的任何操作都不能進行。在對象級使用鎖通常是一種比較粗糙的方法。為什麼要将整個對象都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來通路共享資源?如果一個對象擁有多個資源,就不需要隻為了讓一個線程使用其中一部分資源,就将所有線程都鎖在外面。由于每個對象都有鎖,是以可以使用虛拟對象來上鎖.

  (4)synchronized後面括号裡是類,如果線程進入,則線程在該類中所有操作不能進行,包括靜态變量和靜态方法,實際上,對于含有靜态方法和靜态變量的代碼塊的同步,我們通常用4來加鎖

以上4種之間的關系:

鎖是和對象相關聯的,每個對象有一把鎖,為了執行synchronized語句,線程必須能夠獲得synchronized語句中表達式指定的對象鎖,一個對象隻有一把鎖,被一個線程獲得之後它就不再擁有這把鎖,線程在執行完synchronized語句後,将獲得鎖交還給對象。在方法前面加上synchronized修飾符即可以将一個方法聲明為同步化方法。同步化方法在執行之前獲得一個鎖。如果這是一個類方法,那麼獲得的鎖是和聲明方法的類相關的Class類對象的鎖,如果這個一個執行個體方法,那麼此鎖是this對象的鎖。

8,public final void wait(long timeout) throwsInterruptedException

參數:

timeout - 要等待的最長時間(以毫秒為機關)。 

抛出: 

IllegalArgumentException - 如果逾時值為負。 

IllegalMonitorStateException - 如果目前線程不是此對象螢幕的所有者。 

InterruptedException - 如果在目前線程等待通知之前或者正在等待通知時,任何線程中斷了目前線程。在抛出此異常時,目前線程的中斷狀态被清除。

public final void wait(long timeout, int nanos) throwsInterruptedException

參數:

timeout - 要等待的最長時間(以毫秒為機關)。

nanos - 額外時間(以毫微秒為機關,範圍是 0-999999)。 

抛出: 

IllegalArgumentException - 如果逾時值是負數,或者毫微秒值不在 0-999999範圍内。 

IllegalMonitorStateException - 如果目前線程不是此對象螢幕的所有者。 

InterruptedException - 如果在目前線程等待通知之前或者正在等待通知時,任何線程中斷了目前線程。在抛出此異常時,目前線程的中斷狀态被清除。

public final void wait()(等價于wait(0))throws InterruptedException

抛出: 

IllegalMonitorStateException - 如果目前線程不是此對象螢幕的所有者。 

InterruptedException - 如果在目前線程等待通知之前或者正在等待通知時,任何線程中斷了目前線程。在抛出此異常時,目前線程的中斷狀态被清除。

9,public final void notify()喚醒在此對象螢幕上等待的單個線程。如果所有線程都在此對象上等待,則會選擇喚醒其中一個線程。選擇是任意性的,并在對實作做出決定時發生。線程通過調用其中一個 wait 方法,在對象的螢幕上等待。

直到目前線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程将以正常方式與在該對象上主動同步的其他所有線程進行競争;例如,喚醒的線程在作為鎖定此對象的下一個線程方面沒有可靠的特權或劣勢。

此方法隻應由作為此對象螢幕的所有者的線程來調用。通過以下三種方法之一,線程可以成為此對象螢幕的所有者:

通過執行此對象的同步執行個體方法。 

通過執行在此對象上進行同步的 synchronized語句的正文。 

對于 Class 類型的對象,可以通過執行該類的同步靜态方法。 

一次隻能有一個線程擁有對象的螢幕。 

抛出: 

IllegalMonitorStateException - 如果目前線程不是此對象螢幕的所有者。

10,public final void notifyAll()喚醒在此對象螢幕上等待的所有線程。線程通過調用其中一個 wait方法,在對象的螢幕上等待。

直到目前線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程将以正常方式與在該對象上主動同步的其他所有線程進行競争;例如,喚醒的線程在作為鎖定此對象的下一個線程方面沒有可靠的特權或劣勢。

此方法隻應由作為此對象螢幕的所有者的線程來調用。有關線程能夠成為螢幕所有者的方法的描述,請參閱 notify方法。 

抛出: 

IllegalMonitorStateException - 如果目前線程不是此對象螢幕的所有者。

11,練習題:子線程循環10次,接着主線程循環100次,接着又回到子線程循環10次,接着再回到主線程又循環100次,如此循環50次,請寫出程式

這道題我和張老師做得不一樣,他是把主線程循環的100次和和子線程循環10次寫成兩個方法的,而我是寫成一個方法通過傳遞所需循環的次數的參數來實作的

1.    public class ThreadTest {  

2.        public static void main(String[] args) {  

3.            final ThreadCommunication threadCommunication = new ThreadCommunication();  

4.            new Thread(new Runnable() {  

5.                @Override  

6.                public void run() {  

7.                    for (int i = 1; i <= 50; i++) {  

8.                        threadCommunication.print(10);  

9.                    }  

10.              }  

11.          }).start();  

12.          for (int i = 1; i <= 50; i++) {  

13.              threadCommunication.print(100);  

14.          }  

15.      }  

16.  }  

17.    

18.  class ThreadCommunication {  

19.      private int temp;  

20.      private boolean flag = true;  

21.    

22.      public synchronized void print(int num) {  

23.          while (!flag & 10 == num || flag & 100 == num) {  

24.              try {  

25.                  this.wait();  

26.              } catch (InterruptedException e) {  

27.                  e.printStackTrace();  

28.              }  

29.          }  

30.          for (temp = num; temp > 0; temp--) {  

31.              System.out.println(Thread.currentThread().getName() + temp);  

32.          }  

33.    

34.          flag = false == flag ? true : false;  

35.          this.notify();  

36.      }  

37.  }  

12,張老師在視訊中提到了捕獲線程死亡事件,這個在課堂上沒有找到方法,我就好奇的也試着看了看API,這是我個人的捕獲線程死亡事件做法,也不知道是不是這麼一回事

1.    public class CatchThreadTerminate {  

2.        public static void main(String[] args) {  

3.            final Thread thread = new Thread(new Runnable() {  

4.                @Override  

5.                public void run() {  

6.                    for (int i = 0; i <= 100; i++) {  

7.                        System.out.println(i);  

8.                    }  

9.                }  

10.          });  

11.          thread.start();// 啟動thread線程  

12.          new Thread(new Runnable() {  

13.    

14.              @Override  

15.              public void run() {  

16.                  while (true) {  

17.                      if (Thread.State.TERMINATED == thread.getState()) {  

18.                            

19.                          System.out.println("線程死亡");  

20.                          break;// 已經捕獲到thread的死亡,結束監聽  

21.                      }  

22.                  }  

23.              }  

24.    

25.          }).start();// 啟動一個線程來監聽thread線程是否是亡  

26.      }  

27.  }