亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

線程、多線程與線程池總結

2019-11-11 04:37:09
字體:
來源:轉載
供稿:網友

先看幾個概念:

線程:進程中負責程序執行的執行單元。一個進程中至少有一個線程。

多線程:解決多任務同時執行的需求,合理使用CPU資源。多線程的運行是根據CPU切換完成,如何切換由CPU決定,因此多線程運行具有不確定性。

線程池:基本思想還是一種對象池的思想,開辟一塊內存空間,里面存放了眾多(未死亡)的線程,池中線程執行調度由池管理器來處理。當有線程任務時,從池中取一個,執行完成后線程對象歸池,這樣可以避免反復創建線程對象所帶來的性能開銷,節省了系統的資源。

如果對線程概念不清晰的話,不妨先看看《我是一個線程》這篇文章,擬人化的故事闡述線程的工作原理。

線程

創建線程的兩種方式:

一、繼承Thread類,擴展線程。

繼承Thread類,覆蓋run()方法。

創建線程對象并用start()方法啟動線程。

面試題

1)線程和進程有什么區別?

一個進程是一個獨立(self contained)的運行環境,它可以被看作一個程序或者一個應用。而線程是在進程中執行的一個任務。線程是進程的子集,一個進程可以有很多線程,每條線程并行執行不同的任務。不同的進程使用不同的內存空間,而所有的線程共享一片相同的內存空間。別把它和棧內存搞混,每個線程都擁有單獨的棧內存用來存儲本地數據。

2)如何在java中實現線程?

創建線程有兩種方式:

一、繼承 Thread 類,擴展線程。

二、實現 Runnable 接口。

3)Thread 類中的 start() 和 run() 方法有什么區別?

調用 start() 方法才會啟動新線程;如果直接調用 Thread 的 run() 方法,它的行為就會和普通的方法一樣;為了在新的線程中執行我們的代碼,必須使用 Thread.start() 方法。

擴展

Android 系統接口 HandlerThread 繼承了 Thread,它是一個可以使用 Handler 的 Thread,一個具有消息循環的線程。run()方法中通過 Looper.PRepare() 來創建消息隊列,通過 Looper.loop() 來開啟消息循環??梢栽?run() 方法中執行耗時的任務,而 HandlerThread 內部創建了消息隊列外界需要通過 Handler 的方式來通知 HandlerThread 執行一個具體任務;HandlerThread 的 run() 方法是一個無限的循環,可以通過它的 quite() 或 quitSafely() 方法來終止線程的執行;

二、實現Runnable接口。

面試題

1)用 Runnable 還是 Thread ?

我們都知道可以通過繼承 Thread 類或者調用 Runnable 接口來實現線程,問題是,創建線程哪種方式更好呢?什么情況下使用它?這個問題很容易回答,如果你知道Java不支持類的多重繼承,但允許你調用多個接口。所以如果你要繼承其他類,當然是調用Runnable接口更好了。

2)Runnable 和 Callable 有什么不同?

Runnable 和 Callable 都代表那些要在不同的線程中執行的任務。Runnable 從 JDK1.0 開始就有了,Callable 是在 JDK1.5 增加的。它們的主要區別是 Callable 的 call() 方法可以返回值和拋出異常,而 Runnable 的 run() 方法沒有這些功能。Callable 可以返回裝載有計算結果的 Future 對象。

?注意:這面第二個面試題主要是為了引出下面的擴展,原諒我這樣為難人的出場。

擴展

先看一下 Runnable 和 Callable 的源碼

可以得出:

1)Callable 接口下的方法是 call(),Runnable 接口的方法是 run()。

2)Callable 的任務執行后可返回值,而 Runnable 的任務是不能返回值的。

3)call() 方法可以拋出異常,run()方法不可以的。

4)運行 Callable 任務可以拿到一個 Future 對象,表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,并檢索計算的結果。通過 Future 對象可以了解任務執行情況,可取消任務的執行,還可獲取執行結果。

但是,但是,凡事都有但是嘛…

單獨使用 Callable,無法在新線程中(new Thread(Runnable r))使用,Thread 類只支持 Runnable。不過 Callable 可以使用 ExecutorService (又拋出一個概念,這個概念將在下面的線程池中說明)。

上面又提到了 Future,看一下 Future 接口:

Future 定義了5個方法:

1)boolean cancel(boolean mayInterruptIfRunning):試圖取消對此任務的執行。如果任務已完成、或已取消,或者由于某些其他原因而無法取消,則此嘗試將失敗。當調用 cancel() 時,如果調用成功,而此任務尚未啟動,則此任務將永不運行。如果任務已經啟動,則 mayInterruptIfRunning 參數確定是否應該以試圖停止任務的方式來中斷執行此任務的線程。此方法返回后,對 isDone() 的后續調用將始終返回 true。如果此方法返回 true,則對 isCancelled() 的后續調用將始終返回 true。

2)boolean isCancelled():如果在任務正常完成前將其取消,則返回 true。

3)boolean isDone():如果任務已完成,則返回 true。 可能由于正常終止、異?;蛉∠瓿桑谒羞@些情況中,此方法都將返回 true。

4)V get()throws InterruptedException,ExecutionException:如有必要,等待計算完成,然后獲取其結果。

5)V get(long timeout,TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException: 如有必要,最多等待為使計算完成所給定的時間之后,獲取其結果(如果結果可用)。

看來 Future 接口也不能用在線程中,那怎么用,誰實現了 Future 接口呢?答:FutureTask。

FutureTask 實現了 Runnable 和 Future,所以兼顧兩者優點,既可以在 Thread 中使用,又可以在 ExecutorService 中使用。

看完上面啰哩啰嗦的介紹后,下面我們具體看一下具體使用的示例:

使用 FutureTask 的好處是 FutureTask 是為了彌補 Thread 的不足而設計的,它可以讓程序員準確地知道線程什么時候執行完成并獲得到線程執行完成后返回的結果。FutureTask 是一種可以取消的異步的計算任務,它的計算是通過 Callable 實現的,它等價于可以攜帶結果的 Runnable,并且有三個狀態:等待、運行和完成。完成包括所有計算以任意的方式結束,包括正常結束、取消和異常。

查看具體操作代碼請參考 《個人學習項目DroidStudy》(https://github.com/sfsheng0322/In-depthStudy),感謝您的關注。

多線程

多線程的概念很好理解就是多條線程同時存在,但要用好多線程確不容易,涉及到多線程間通信,多線程共用一個資源等諸多問題。

使用多線程的優缺點:

優點:

1)適當的提高程序的執行效率(多個線程同時執行)。

2)適當的提高了資源利用率(CPU、內存等)。

缺點:

1)占用一定的內存空間。

2)線程越多CPU的調度開銷越大。

3)程序的復雜度會上升。

對于多線程的示例代碼感興趣的可以自己寫Demo啦,去運行體會,下面我主要列出一些多線程的技術點。

synchronized

同步塊大家都比較熟悉,通過 synchronized 關鍵字來實現;所有加上 synchronized 的方法和塊語句,在多線程訪問的時候,同一時刻只能有一個線程能夠訪問。

wait()、notify()、notifyAll()

這三個方法是 java.lang.Object 的 final native 方法,任何繼承 java.lang.Object 的類都有這三個方法。它們是Java語言提供的實現線程間阻塞和控制進程內調度的底層機制,平時我們會很少用到的。

wait():

導致線程進入等待狀態,直到它被其他線程通過notify()或者notifyAll喚醒,該方法只能在同步方法中調用。

notify():

隨機選擇一個在該對象上調用wait方法的線程,解除其阻塞狀態,該方法只能在同步方法或同步塊內部調用。

notifyAll():

解除所有那些在該對象上調用wait方法的線程的阻塞狀態,同樣該方法只能在同步方法或同步塊內部調用。

調用這三個方法中任意一個,當前線程必須是鎖的持有者,如果不是會拋出一個 IllegalMonitorStateException 異常。

wait() 與 Thread.sleep(long time) 的區別

sleep():在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),該線程不丟失任何監視器的所屬權,sleep() 是 Thread 類專屬的靜態方法,針對一個特定的線程。

wait() 方法使實體所處線程暫停執行,從而使對象進入等待狀態,直到被 notify() 方法通知或者 wait() 的等待的時間到。sleep() 方法使持有的線程暫停運行,從而使線程進入休眠狀態,直到用 interrupt 方法來打斷他的休眠或者 sleep 的休眠的時間到。

wait() 方法進入等待狀態時會釋放同步鎖,而 sleep() 方法不會釋放同步鎖。所以,當一個線程無限 sleep 時又沒有任何人去 interrupt 它的時候,程序就產生大麻煩了,notify() 是用來通知線程,但在 notify() 之前線程是需要獲得 lock 的。另個意思就是必須寫在 synchronized(lockobj) {…} 之中。wait() 也是這個樣子,一個線程需要釋放某個 lock,也是在其獲得 lock 情況下才能夠釋放,所以 wait() 也需要放在 synchronized(lockobj) {…} 之中。

volatile 關鍵字

volatile 是一個特殊的修飾符,只有成員變量才能使用它。在Java并發程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile 變量可以保證下一個讀取操作會在前一個寫操作之后發生。線程都會直接從內存中讀取該變量并且不緩存它。這就確保了線程讀取到的變量是同內存中是一致的。

ThreadLocal 變量

ThreadLocal 是Java里一種特殊的變量。每個線程都有一個 ThreadLocal 就是每個線程都擁有了自己獨立的一個變量,競爭條件被徹底消除了。如果為每個線程提供一個自己獨有的變量拷貝,將大大提高效率。首先,通過復用減少了代價高昂的對象的創建個數。其次,你在沒有使用高代價的同步或者不變性的情況下獲得了線程安全。

join() 方法

join() 方法定義在 Thread 類中,所以調用者必須是一個線程,join() 方法主要是讓調用該方法的 Thread 完成 run() 方法里面的東西后,再執行 join() 方法后面的代碼,看下下面的”意思”代碼:

啟動 t1 后,調用了 join() 方法,直到 t1 的計數任務結束,才輪到 t2 啟動,然后 t2 才開始計數任務,兩個線程是按著嚴格的順序來執行的。如果 t2 的執行需要依賴于 t1 中的完整數據的時候,這種方法就可以很好的確保兩個線程的同步性。

Thread.yield() 方法

Thread.sleep(long time):線程暫時終止執行(睡眠)一定的時間。 

Thread.yield():線程放棄運行,將CPU的控制權讓出。 

這兩個方法都會將當前運行線程的CPU控制權讓出來,但 sleep() 方法在指定的睡眠時間內一定不會再得到運行機會,直到它的睡眠時間完成;而 yield() 方法讓出控制權后,還有可能馬上被系統的調度機制選中來運行,比如,執行yield()方法的線程優先級高于其他的線程,那么這個線程即使執行了 yield() 方法也可能不能起到讓出CPU控制權的效果,因為它讓出控制權后,進入排隊隊列,調度機制將從等待運行的線程隊列中選出一個等級最高的線程來運行,那么它又(很可能)被選中來運行。

擴展

線程調度策略

(1) 搶占式調度策略

Java運行時系統的線程調度算法是搶占式的。Java運行時系統支持一種簡單的固定優先級的調度算法。如果一個優先級比其他任何處于可運行狀態的線程都高的線程進入就緒狀態,那么運行時系統就會選擇該線程運行。新的優先級較高的線程搶占了其他線程。但是Java運行時系統并不搶占同優先級的線程。換句話說,Java運行時系統不是分時的。然而,基于Java Thread類的實現系統可能是支持分時的,因此編寫代碼時不要依賴分時。當系統中的處于就緒狀態的線程都具有相同優先級時,線程調度程序采用一種簡單的、非搶占式的輪轉的調度順序。

(2) 時間片輪轉調度策略

有些系統的線程調度采用時間片輪轉調度策略。這種調度策略是從所有處于就緒狀態的線程中選擇優先級最高的線程分配一定的CPU時間運行。該時間過后再選擇其他線程運行。只有當線程運行結束、放棄(yield)CPU或由于某種原因進入阻塞狀態,低優先級的線程才有機會執行。如果有兩個優先級相同的線程都在等待CPU,則調度程序以輪轉的方式選擇運行的線程。

以上把這些技術點總結出來,后面我會把多線程這塊的示例代碼更新到 《個人學習項目DroidStudy》,感謝您的關注。

線程池

創建多個線程不光麻煩而且相對影響系統性能,接下來讓我看看使用線程池來操作多線程。我把自己的 《個人學習項目DroidStudy》 中線程池轉成一個 gif 效果圖,大家可以實際把玩下去感受線程池的原理,有興趣的同學也可以先 star 下,我會在接下來的幾個月把這個學習的Demo工程完善好。

線程池的優點

1)避免線程的創建和銷毀帶來的性能開銷。

2)避免大量的線程間因互相搶占系統資源導致的阻塞現象。

3}能夠對線程進行簡單的管理并提供定時執行、間隔執行等功能。

再擼一擼概念

Java里面線程池的頂級接口是 Executor,不過真正的線程池接口是 ExecutorService, ExecutorService 的默認實現是 ThreadPoolExecutor;普通類 Executors 里面調用的就是 ThreadPoolExecutor。

照例看一下各個接口的源碼:

下面我創建的一個線程池:

Executors%20提供四種線程池:

1)newCachedThreadPool%20是一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。對于執行很多短期異步任務的程序而言,這些線程池通常可提高程序性能。調用%20execute()%20將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程并添加到池中。終止并從緩存中移除那些已有%2060%20秒鐘未被使用的線程。因此,長時間保持空閑的線程池不會使用任何資源。注意,可以使用%20ThreadPoolExecutor%20構造方法創建具有類似屬性但細節不同(例如超時參數)的線程池。

2)newSingleThreadExecutor%20創建是一個單線程池,也就是該線程池只有一個線程在工作,所有的任務是串行執行的,如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它,此線程池保證所有任務的執行順序按照任務的提交順序執行。

3)newFixedThreadPool%20創建固定大小的線程池,每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小,線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那么線程池會補充一個新線程。

4)newScheduledThreadPool%20創建一個大小無限的線程池,此線程池支持定時以及周期性執行任務的需求。

通過%20ThreadPoolExecutor%20的構造函數,擼一擼線程池相關參數的概念:

1)corePoolSize:線程池的核心線程數,一般情況下不管有沒有任務都會一直在線程池中一直存活,只有在 ThreadPoolExecutor 中的方法 allowCoreThreadTimeOut(boolean value) 設置為 true 時,閑置的核心線程會存在超時機制,如果在指定時間沒有新任務來時,核心線程也會被終止,而這個時間間隔由第3個屬性 keepAliveTime 指定。

2)maximumPoolSize:線程池所能容納的最大線程數,當活動的線程數達到這個值后,后續的新任務將會被阻塞。

3)keepAliveTime:控制線程閑置時的超時時長,超過則終止該線程。一般情況下用于非核心線程,只有在 ThreadPoolExecutor 中的方法 allowCoreThreadTimeOut(boolean value) 設置為 true時,也作用于核心線程。

4)unit:用于指定 keepAliveTime 參數的時間單位,TimeUnit 是個 enum 枚舉類型,常用的有:TimeUnit.HOURS(小時)、TimeUnit.MINUTES(分鐘)、TimeUnit.SECONDS(秒) 和 TimeUnit.MILLISECONDS(毫秒)等。

5)workQueue:線程池的任務隊列,通過線程池的 execute(Runnable command) 方法會將任務 Runnable 存儲在隊列中。

6)threadFactory:線程工廠,它是一個接口,用來為線程池創建新線程的。

線程池的關閉

ThreadPoolExecutor 提供了兩個方法,用于線程池的關閉,分別是 shutdown() 和 shutdownNow()。

shutdown():不會立即的終止線程池,而是要等所有任務緩存隊列中的任務都執行完后才終止,但再也不會接受新的任務。

shutdownNow():立即終止線程池,并嘗試打斷正在執行的任務,并且清空任務緩存隊列,返回尚未執行的任務。

面試題

1)什么是 Executor 框架?

Executor框架在Java 5中被引入,Executor 框架是一個根據一組執行策略調用、調度、執行和控制的異步任務的框架。

無限制的創建線程會引起應用程序內存溢出,所以創建一個線程池是個更好的的解決方案,因為可以限制線程的數量并且可以回收再利用這些線程。利用 Executor 框架可以非常方便的創建一個線程池。

2)Executors 類是什么?

Executors為Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 類提供了一些工具方法。Executors 可以用于方便的創建線程池。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品国产福利国产秒拍| 国产精品丝袜一区二区三区| 日韩在线欧美在线国产在线| 亚洲自拍偷拍网址| 黑人巨大精品欧美一区二区三区| 91久久嫩草影院一区二区| 欧美成人中文字幕在线| 一区二区三区国产在线观看| 欧美日韩一二三四五区| 97在线视频免费| 亚洲欧美国产视频| www.色综合| 欧美乱人伦中文字幕在线| 成人在线精品视频| 欧美伊久线香蕉线新在线| 91久久久久久国产精品| 久久久久久这里只有精品| 亚洲乱码国产乱码精品精天堂| 欧美激情国产精品| 欧美一级片免费在线| 欧洲成人性视频| 亚洲精品国产精品乱码不99按摩| 成人欧美一区二区三区黑人| 国产精品手机播放| 中文字幕日韩精品有码视频| 国产一区欧美二区三区| 欧美电影免费观看高清完整| 亚洲精品小视频| 日韩成人av在线播放| 欧美劲爆第一页| 在线电影av不卡网址| 日本在线观看天堂男亚洲| 成人av番号网| 亚洲欧洲成视频免费观看| 国产精品亚洲精品| 在线国产精品播放| 久久精品中文字幕电影| 亚洲美女激情视频| 国产成人精品日本亚洲| 久久精品99久久久久久久久| 成人黄色大片在线免费观看| 日产精品99久久久久久| 欧美视频在线免费| 欧美一级电影久久| 久久久久久久久91| 美日韩精品免费观看视频| 亚洲欧美日韩国产中文专区| 日韩精品中文在线观看| 欧美成人手机在线| 成人欧美一区二区三区黑人| 91色在线视频| 日韩精品亚洲精品| 欧美老女人bb| 96国产粉嫩美女| 亚洲综合中文字幕在线| 亚洲成人黄色网| 亚洲天堂日韩电影| 色七七影院综合| 色妞一区二区三区| 国产精品aaaa| 色综合天天综合网国产成人网| 91午夜理伦私人影院| 欧美日韩免费区域视频在线观看| 亚洲字幕在线观看| 久久久久久久亚洲精品| 亚洲人成在线免费观看| 久久亚洲精品小早川怜子66| 欧美日韩国产在线| 一区二区欧美激情| 日韩av电影在线播放| 久久成年人免费电影| 久久九九热免费视频| 亚洲视频在线播放| 深夜福利91大全| 91精品综合久久久久久五月天| 日韩中文在线中文网在线观看| 亚洲成人精品久久久| 91免费福利视频| 国产精品日韩欧美| 日韩免费看的电影电视剧大全| 日韩在线欧美在线国产在线| 亚洲欧美三级在线| 亚洲成人免费在线视频| 国产精品老女人视频| 国产精品亚洲激情| 日韩免费不卡av| 亚洲影院色无极综合| 亚洲欧美精品中文字幕在线| 久久精品91久久久久久再现| 一区二区三区美女xx视频| 国产视频精品自拍| 欧美日韩在线视频观看| 中文字幕亚洲欧美| 亚洲成人动漫在线播放| 美日韩精品免费视频| 欧美午夜精品久久久久久人妖| xxxxxxxxx欧美| 国产脚交av在线一区二区| 精品中文字幕视频| 美日韩精品视频免费看| 精品国产户外野外| 亚洲在线观看视频| 91av视频在线免费观看| 久久影院中文字幕| 午夜精品福利电影| 尤物九九久久国产精品的分类| 国产精品自产拍在线观看中文| 久久伊人精品一区二区三区| 97欧美精品一区二区三区| 欧美电影在线观看网站| 国产女人精品视频| 亚洲日本欧美中文幕| 揄拍成人国产精品视频| 欧美日韩综合视频网址| 久久久久久尹人网香蕉| 欧美极品少妇xxxxⅹ免费视频| 成人国产精品一区二区| 日韩中文有码在线视频| 欧美极品美女视频网站在线观看免费| 国产欧美一区二区三区在线| 欧美肥婆姓交大片| 久久久久女教师免费一区| 日韩精品电影网| 97成人精品区在线播放| 欧美电影免费观看| 欧美午夜视频一区二区| 韩国欧美亚洲国产| 亚洲精品视频在线观看视频| 久久国产精品久久国产精品| 国产精品美女久久久久av超清| 久久精品这里热有精品| 日韩av电影在线网| 97欧美精品一区二区三区| 77777少妇光屁股久久一区| 亚洲人成电影网站色xx| 欧美亚洲午夜视频在线观看| 亚洲第一精品久久忘忧草社区| 亚洲加勒比久久88色综合| 欧美激情亚洲一区| 91探花福利精品国产自产在线| 亚洲男人天天操| 色青青草原桃花久久综合| 国内久久久精品| 国产成人精彩在线视频九色| 国产成人高清激情视频在线观看| 精品在线欧美视频| 亚洲自拍偷拍区| 97不卡在线视频| 久久综合亚洲社区| 亚洲成人av资源网| 精品久久香蕉国产线看观看gif| 久久av资源网站| 国产欧美亚洲视频| 久久久久久久影院| 成人黄色av网| 亚洲精品美女在线观看播放| 91欧美日韩一区| 久久免费视频观看| 国产精品成人观看视频国产奇米| 欧美孕妇性xx| 国产午夜精品免费一区二区三区| 日韩av电影免费观看高清| 97精品国产91久久久久久| 欧美成人一区二区三区电影|