Android 多線程之幾個基本問題

Android中的進程和線程

  • Android中的一個應用程序一般就對應著一個進程,多進程的情況可以參考Android 多進程通信之幾個基本問題
  • Android中更常見的是多線程的情況,一個應用程序中一般都有包括UI線程等多個線程。Android中規定網絡訪問必須在子線程中進行,而操作更新UI則只能在UI線程。
  • 常見的網絡請求庫,如OkHttp、Volly等都為我們封裝好了線程池,所以我們在進行網絡請求時一般不是很能直觀地感受到創建線程以及切換線程的過程。
  • 線程是一種很寶貴的資源,要避免頻繁創建銷毀線程,一般推薦用線程池來管理線程。

線程的狀態

線程可能存在6種不同的狀態:新創建(New)、可運行(Runnable)、阻塞狀態(Blocked)、等待狀態(Waiting)、限期等待(Timed Waiting)、終止狀態(Terminated)

  • 新創建(New):創建后但還未啟動的線程(還沒有調用start方法)處于這種狀態
  • 可運行(Runnable):一旦調用了start方法,線程就處于這種狀態。需要注意的是此時線程可能正在執行,也可能在等待CPU分配執行的時間
  • 阻塞狀態(Blocked):表示線程被鎖阻塞,等待獲取到一個排他鎖。在程序等待進入同步區域時,線程將進入這種狀態
  • 等待狀態(Waiting):處于這種狀態的線程不會被分配CPU執行時間,它們要等待被其他線程顯示地喚醒。調用以下方法會讓線程進入這種狀態:

    • 沒有設置Timeout參數的Object.wait()方法
    • 沒有設置Timeout參數的Thread.join()方法
  • 限期等待(Timed Waiting):與等待狀態(Waiting)不同的是,處于這種狀態的線程不需要等待其它線程喚醒,在一定時間之后會由系統喚醒。調用以下方法會讓線程進入這種狀態:

    • Thread.sleep()方法
    • 設置了Timeout參數的Object.wait()方法
    • 設置了Timeout參數的Thread.join()方法
  • 終止狀態(Terminated):表示線程已經執行完畢。導致線程終止有2種情況:

    • 線程的run方法執行完畢,正常退出
    • 因為一個沒有捕獲的異常而終止了run方法

創建線程

創建線程一般有如下幾種方式:繼承Thread類;實現Runnable接口;實現Callable接口

  • 繼承Thread類,重寫run方法
public class TestThread extends Thread {@Overridepublic void run() {System.out.println("Hello World");}public static void main(String[] args) {Thread mThread = new TestThread();mThread.start();}
}
  • 實現Runnable接口,并實現run方法
public class TestRunnable implements Runnable {@Overridepublic void run() {System.out.println("Hello World");}public static void main(String[] args) {TestRunnable mTestRunnable = new TestRunnable();Thread mThread = new Thread(mTestRunnable);mThread.start();}
}
  • 實現Callable接口,重寫call方法

    • Callable可以在任務接受后提供一個返回值而Runnable不行
    • Callable的call方法可以拋出異常,Runnable的run方法不行
    • 運行Callable可以拿到一個Future對象,表示計算的結果,通過Future的get方法可以拿到異步計算的結果,不過當前線程會阻塞。
public class TestCallable {public static class MyTestCallable implements Callable<String> {@Overridepublic String call() throws Exception {//call方法可以提供返回值,而Runnable不行return "Hello World";}}public static void main(String[] args) {MyTestCallable myTestCallable = new MyTestCallable();//手動創建線程池ExecutorService executorService = new ThreadPoolExecutor(1,1,0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10));//運行callable可以拿到一個Future對象Future future = executorService.submit(myTestCallable);try {//等待線程結束,future.get()方法會使當前線程阻塞System.out.println(future.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}
  • 以上三種方式就是常見的創建線程的方式。推薦使用實現Runnable接口的方法。

線程中斷

  • 當一個線程調用interrupt方法時,線程的中斷標識為將被設置成true
  • 通過Thread.currentThread().isInterrupted()方法可以判斷線程是否應該被中斷
  • 可以通過調用Thread.interrupted()對中斷標志位進行復位(設置為false)
  • 如果一個線程處于阻塞狀態,線程在檢查中斷標志位時如果發現中斷標志位為true,則會在阻塞方法處拋出InterruptedException異常,并且在拋出異常前會將中斷標志位復位,即重新設置為false
  • 不要在代碼底層捕獲InterruptedException異常后不做處理

同步的幾種方法

同步的方式一般有如下3種:volatile關鍵字、synchronized關鍵字、重入鎖ReentrantLock

volatile關鍵字
  • volatile關鍵字實現多線程安全關鍵在于它的可見性特性,但它需要滿足一些條件才能保證線程安全,具體可以查看文章深入理解Java虛擬機(八)之Java內存模型
  • 在用volatile關鍵字來實現多線程安全時需要注意volatile不保證原子性,也就是不能用于一些自增、自減等操作,也不能用于一些不變式中,自增、自減比較好理解,下面看看不變式的情況
public class VolatileTest {private volatile int lower,upper;public int getLower() {return lower;}public void setLower(int value) {if (value > upper) {throw new IllegalArgumentException();}this.lower = value;}public int getUpper() {return upper;}public void setUpper(int value) {if (value < lower) {throw new IllegalArgumentException();}this.upper = value;}
}
  • 上面的例子中,如果初始值是(0,5),線程A調用setLower(4),線程B調用setUpper(3),顯然最后結果就會變成(4,3)了
  • volatile使用的場景常見的有作為狀態標志以及DCL單例模式
synchronized關鍵字和重入鎖ReentrantLock
  • synchronized關鍵字比較常見,可以用于同步方法也可以用于同步代碼塊,一般推薦用同步方法,同步代碼塊的安全性不高。
  • 重入鎖ReentrantLock相比synchronized提供了一些獨有的特性:可以綁定多個解鎖的條件Condition、可以實現公平鎖、可以設置放棄等待獲取鎖的時間。
public class ReentrantLockTest {private Lock mLock = new ReentrantLock();//true,表示實現公平鎖<!--private Lock mLock = new ReentrantLock(true);-->private Condition condition;private void thread1() throws InterruptedException{mLock.lock();try {condition = mLock.newCondition();condition.await();System.out.println("thread1:Hello World");}finally {mLock.unlock();}}private void thread2() throws InterruptedException{mLock.lock();try {System.out.println("thread2:Hello World");condition.signalAll();}finally {mLock.unlock();}}
}
  • 一個ReentrantLock有多個相關的Condition,調用Condition的await方法會讓當前線程進入該條件的等待集并阻塞,直到另一個線程調用了同一個條件的signalAll方法激活因為這個條件而進入阻塞的所有線程
  • 一般線程同步用得比較多的還是synchronized同步方法和一些java.util.concurrent包提供的一些類

如何安全的終止線程

雖然我們一般都是利用線程池來管理線程而不會直接顯示地創建線程,但是作為線程相關知識的一部分,我們還是要了解如何安全地終止一個線程。

要安全地終止一個線程,一般有2種方法:中斷和標志位

(1)利用中斷來終止線程

Thread thread = new Thread(new Runnable() {@Overridepublic void run() {while (!Thread.currentThread().isInterrupted()) {//do something}}
});//當我們調用Thread的interrupt方法時,線程就會退出循環停止了。
thread.interrupt();

(2)通過標志位

private static class MyRunnable implements Runnable {//控制線程的標志位,需要用 volatile關鍵字   private volatile boolean on = true;@Overridepublic void run() {while (on) {//do something }}public void cancel() {on = false;}
}//啟動線程
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);//終止線程
myRunnable.cancel();

              歡迎關注我的微信公眾號,期待與你一起學習,一起交流,一起成長!

AntDream

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277193.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277193.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277193.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Web下的整體測試

隨著Internet的日益普及&#xff0c;現在基于B/S結構的大型應用越來越多&#xff0c;可如何對這些應用進行測試成為日益迫切的問題。有許多測試人員來信問我B/S的測試如何做&#xff0c;由于工作較繁忙&#xff0c;對大家提出的問題也是頭痛醫頭腳痛醫腳&#xff0c;沒有對WEB的…

用計算機算算術平方根順序是ON然后是什么,第2課時用計算器求一個正數的算術平方根.ppt...

1.比較下列各組數的大小&#xff1a;(1) 與(2) 與 8依次按鍵顯示&#xff1a;1.732 050 808例3 小麗想用一塊面積為400 cm2的正方形紙片&#xff0c;沿著邊的方向剪出一塊面積為300 cm2的長方形紙片&#xff0c;使它的長寬之比為3:2&#xff0e;她不知能否裁得出來&#xff0c;…

MySQL 命令

版權聲明&#xff1a;本文首發 http://asing1elife.com &#xff0c;轉載請注明出處。 https://blog.csdn.net/asing1elife/article/details/82892834 MySQL 一些常見命令 更多精彩 更多技術博客&#xff0c;請移步 asing1elife’s blog 查看版本號 mysql -V重啟/啟動/停止 mys…

Bookshelf 2 簡單DFS

鏈接&#xff1a;https://ac.nowcoder.com/acm/contest/993/C來源&#xff1a;牛客網 題目描述 Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly, and now the only available space is at the top.FJ…

一步一步SharePoint 2007之五:向網站中添加一個子網站

一步一步SharePoint 2007之五&#xff1a;向網站中添加一個子網站摘要感受完看到成果的激動&#xff0c;感受完鄰家女孩的漂亮、可愛和端莊&#xff0c;不要停止&#xff0c;來&#xff0c;讓我們一起來動手打造心目中的完美女神吧&#xff01;本篇文章將介紹如何向一個網站中添…

微型計算機系統分為哪幾個層次,計算機系統分為哪4層?

滿意答案al053192014.06.23采納率&#xff1a;49% 等級&#xff1a;12已幫助&#xff1a;7516人第一層&#xff1a;物理層(PhysicalLayer)&#xff0c;規定通信設備的機械的、電氣的、功能的和過程的特性&#xff0c;用以建立、維護和拆除物理鏈路連接。具體地講&#xff0c…

ASP.NET Core 基礎教程 - ASP.NET Core 基礎教程 - 簡單教程,簡單編程

原文:ASP.NET Core 基礎教程 - ASP.NET Core 基礎教程 - 簡單教程&#xff0c;簡單編程 ASP.NET Core 是對 ASP.NET 有重大意義的一次重新設計。本章節我們將介紹 ASP.NET Core 中的一些新的概念和它們是如何幫助我們開發現代化的 Web 應用程序 盡管 ASP.NET Core 是跨平臺的&a…

參數初始化

通過以下形式進行參數初始化 self.fc nn.Linear(n_head * d_v, d_model) nn.init.xavier_normal_(self.fc.weight) 轉載于:https://www.cnblogs.com/yeran/p/11197047.html

使用input type=file 上傳文件時需注意

在asp.net的中使用<input typefile />控件上傳文件對文件的大小有限制,默認情況下大概在4m左右,如果上傳再大的文件時就會出頁面無法顯示的錯誤.修改web.config文件中的參數可以設置該控件上傳文件的大小,web.config中配置如下:在<system.web>節點下增加"<…

html模板 循環里if,django模板里循環變量table里想要兩個一行如何控制

2016-8-3 周三做項目時遇到的問題&#xff1a;每個div由循環變量輸出&#xff1a;{% for key,value in formextenddetail %}{{ key }}{{ value }}{% endfor %}但是我想兩個div一行&#xff0c;使用...這種樣子因為我負責的是前端&#xff0c;views這些不是很熟悉&#xff0c;想…

ASP.NET Core Windows 環境配置 - ASP.NET Core 基礎教程 - 簡單教程,簡單編程

原文:ASP.NET Core Windows 環境配置 - ASP.NET Core 基礎教程 - 簡單教程&#xff0c;簡單編程 ASP.NET Core Windows 環境配置 ASP.NET Core 是對 ASP.NET 有重大意義的一次重新設計。本章節我們將介紹 ASP.NET Core 中的一些新的概念和它們是如何幫助我們開發現代化的 Web 應…

Prim算法求最小生成樹

給定一個n個點m條邊的無向圖&#xff0c;圖中可能存在重邊和自環&#xff0c;邊權可能為負數。 求最小生成樹的樹邊權重之和&#xff0c;如果最小生成樹不存在則輸出impossible。 給定一張邊帶權的無向圖G(V, E)&#xff0c;其中V表示圖中點的集合&#xff0c;E表示圖中邊的集合…

用installshield打包的asp.net程序

現在需要打包一個asp.net程序&#xff0c;具體要求如下&#xff1a;1、動態建立web虛擬目錄或web站點&#xff0c;并保存至web.config文件相關字段中。2、動態建立ftp目錄&#xff0c;并保存至web.config文件相關字段中。3、動態建立數據庫聯接類型sql或oracle&#xff0c;對sq…

合肥工業大學計算機學院王院長,王青山(合肥工業大學教授)_百度百科

王青山(合肥工業大學教授)語音編輯鎖定討論上傳視頻本詞條缺少概述圖&#xff0c;補充相關內容使詞條更完整&#xff0c;還能快速升級&#xff0c;趕緊來編輯吧&#xff01;王青山&#xff0c;中國漢族人&#xff0c;合肥工業大學教授&#xff0c;現任中國計算機學會、ACM、IEE…

go 中gcc 編譯問題(gcc.exe fatal error no input files compilation terminated)

2019獨角獸企業重金招聘Python工程師標準>>> 問題背景 在windows 中編譯 go 的pipe時由于pipe依賴sqlite&#xff0c;需要通過cgo進行編譯。出現如下異常 gcc.exe fatal error no input files compilation terminated 問題分析 由于 windows中缺少c 的編譯環境 解決…

35歲以前把下面十件事做好

35歲是青春的后期&#xff0c;35歲以后是收獲的季節&#xff0c;如果你沒有資格說這句話&#xff0c;你將會憎恨自己。所以在35歲以前&#xff0c;在爛漫蓬勃的青春年華里&#xff0c;你最好把下面十件事做好&#xff1a; 第一&#xff0c;學會本行業所需要的一切知識并有所發展…

XCode 10 升級問題總結

一、 library not found for -lstdc.6.0.9 xcode 10 中刪除了內置 libstdc.6.0.9.tbd&#xff0c;工程中一些SDK依賴這個庫&#xff0c;需要把xcode 9.4 的libstdc.6.0.9.tbd 添加到xcode中&#xff0c;重啟xcode。 libstdc.6.0.9.tbd 的下載地址&#xff1a;libstdc.6.0.9 真機…

重心轉移

做了好些時候的題了&#xff0c;發現做題對身體的摧殘比普通的寫代碼還要重的多&#xff0c;為了我的眼睛&#xff0c;還是不要那么賣命的做ACM了&#xff0c;反正這個假期還算是比較有收獲。而且&#xff0c;在沒有指導老師的幫助下做難題&#xff0c;根本就是一條艱巨異常的路…

ArcEngine開發體驗(附許可)

ArcGIS Engine Developer Guide ArcGIS9.0開發文檔《Engine_Developers_Guide.pdf》376 &#xff0c;花了兩三天看完了。guide特點&#xff1a;1 guide里面的基礎性的東西很多&#xff0c;涉及com開發應用&#xff0c;開發語言&#xff0c;環境和ao架構介紹的內容2 介紹.net開發…

安裝mysql-connector-python-8.0.11-py3.6遇到問題

1.提示“This application requires Visual Studio 2015 Redistributable” 下載vc_redist.x86安裝即可。 下載鏈接&#xff1a;https://download.microsoft.com/download/6/D/F/6DF3FF94-F7F9-4F0B-838C-A328D1A7D0EE/vc_redist.x86.exe https://download.microsoft.com/downl…