Android多線程研究(4)——從一道面試題說起

來源:互聯網
上載者:User

標籤:android   c   style   class   blog   code   

有一道這種面試題:開啟一個子線程和主線程同一時候運行,子線程輸出10次後接著主線程輸出100次,如此重複50次。先看以下代碼:

package com.maso.test;/** *  * @author Administrator * 兩個線程,當中是一個主線程,第一個線程先運行輸出10次,主線程接著運行輸出100次,如此重複50次 */public class ThreadTest3 implements Runnable{private static Test test;@Overridepublic void run() {for(int i=0; i<50; i++){test.f1(i);}}public static void main(String[] args) {test = new Test();new Thread(new ThreadTest3()).start();for(int i=0; i<50; i++){test.f2(i);}}/** * 將控制和邏輯及資料分類(該類就是資料) * @author Administrator * */static class Test{private boolean isf1 = true;/** * 輸出10次 */public synchronized void f1(int j){if(!isf1){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}for(int i=1; i<=10; i++){System.out.println(Thread.currentThread().getName() + "第" + j + "次輪巡,輸出" + i);}isf1 = false;notify();}/** * 輸出100次 */public synchronized void f2(int j){if(isf1){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}for(int i=1; i<=100; i++){System.out.println(Thread.currentThread().getName() + "第" + j + "次輪巡,輸出" + i);}isf1 = true;notify();}}}
上面推斷用的是if語句,這樣做看似沒有什麼問題,實際上這樣做是不安全的,由於線程在等待的過程中有可能被假喚醒,所以我們須要使用while語句。另外在使用wait和notify的時候須要注意一下幾點:

1、調用object的wait方法和notity方法時,必須先獲得object的對象鎖(必須寫在synchronized中)。

2、假設調用了object的wait方法,則該線程就放掉了對象鎖。

3、假設A1、A2、A3都在object.wait(),則B調用object.notify()僅僅能喚醒A1、A2、A3中的一個(詳細哪一個由JVM決定)

4、object.notifyAll()能夠喚醒所有。

5、B在喚醒A的時候,B假設還持有對象鎖,則要等到B釋放鎖後,A才有機會運行。

Sleep和Wait有什麼差別?

sleep()並不釋放對象鎖,wait()釋放對象鎖。可是wait()和sleep()都能夠通過interrupt()方法打斷線程的暫停狀態,從而使線程立馬拋出InterruptedException。假設線程A希望馬上結束線程B,則能夠對線程B相應的Thread執行個體調用interrupt方法。假設此刻線程B正在wait/sleep/join,則線程B會立馬拋出InterruptedException,在catch() {} 中直接return就可以安全地結束線程。須要注意的是,InterruptedException是線程自己從內部拋出的,並非interrupt()方法拋出的。對某一線程調用interrupt()時,假設該線程正在運行普通的代碼,那麼該線程根本就不會拋出InterruptedException。可是,一旦該線程進入到wait()/sleep()/join()後,就會立馬拋出InterruptedException。

以下我們來看看線程的生命週期:


實現線程調度的方法例如以下:

1、sleep():該線程是讓線程休眠一定的時間,須要捕獲InterruptedException

2、yield():暫停當前線程,讓同等級優先權的線程運行,假設沒有同等級優先權線程則不會起作用。起作用後會讓出CPU已耗用時間,進入就緒狀態。

3、join():讓一個線程等待調用join方法的線程運行完成後再繼續運行。


看一段代碼:

public class ThreadTest4 implements Runnable{private static int a = 0;@Overridepublic void run() {for(int i=0; i<10; i++){a++;}}public static void main(String[] args) {new Thread(new ThreadTest4()).start();System.out.println(a);}}
這段代碼會輸出10嗎?答案是不會的,由於在啟動子線程後,就立馬輸出了a的值,此時子線程對a還沒有操作。改動例如以下:

public class ThreadTest4 implements Runnable{private static int a = 0;@Overridepublic void run() {for(int i=0; i<10; i++){a++;}}public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new ThreadTest4());t.start();t.join();System.out.println(a);}}
這回輸出了10,join()方法的作用由此可見,它會讓其它線程等待該線程運行完成後再運行。






相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.