1、進程和線程的概念
進程:運行中的應用程序稱為進程,擁有系統資源(cpu、內存)
線程:進程中的一段代碼,一個進程中可以有多段代碼。本身不擁有資源(共享所在進程的資源);
在java中,程序入口被自動創建為主線程,在主線程中可以創建多個子線程。
區別:
1、是否占有資源問題
2、創建或撤銷一個進程所需要的開銷比創建或撤銷一個線程所需要的開銷大。
3、進程為重量級組件,線程為輕量級組件
多進程: 在操作系統中能同時運行多個任務(程序)
多線程: 在同一應用程序中有多個功能流同時執行
已經有了進程,為什么還會需要線程呢?主要原因如下:
- 許多應用程序中,同時發生着多個活動。將這些應用程序分解成多個准並行的線程,程序設計的模型會變成更加簡單。
- 由於線程比進程進行更加輕量,創建和取消更加容易。
- 如果程序是IO密集型,那么多線程執行能夠加快程序的執行速度。(如果是CPU密集型,則沒有這個優勢)
- 在多CPU系統中,多線程是可以真正並行執行的。
2、線程的主要特點
①、不能以一個文件名的方式獨立存在在磁盤中;
②、不能單獨執行,只有在進程啟動后才可啟動;
③、線程可以共享進程相同的內存(代碼與數據)。
3、多線程原理
同一時間,CPU只能處理1條線程,只有1條線程在工作(執行)
多線程並發(同時)執行,其實是CPU快速地在多條線程之間調度(切換)
如果CPU調度線程的時間足夠快,就造成了多線程並發執行的假象
思考:如果線程非常非常多,會發生什么情況?
CPU會在N多線程之間調度,CPU會累死,消耗大量的CPU資源
每條線程被調度執行的頻次會降低(線程的執行效率降低)
4、線程的主要用途
①、利用它可以完成重復性的工作(如實現動畫、聲音等的播放)。
②、從事一次性較費時的初始化工作(如網絡連接、聲音數據文件的加載)。
③、並發執行的運行效果(一個進程多個線程)以實現更復雜的功能
5、多線程(多個線程同時運行)程序的優缺點
優點:
①、可以減輕系統性能方面的瓶頸,因為可以並行操作;
②、提高CPU的處理器的效率,在多線程中,通過優先級管理,可以使重要的程序優先操作,提高了任務管理的靈活性;
另一方面,在多CPU系統中,可以把不同的線程在不同的CPU中執行,真正做到同時處理多任務。
缺點:
1、開啟線程需要占用一定的內存空間(默認情況下,主線程占用1M,子線程占用512KB),如果開啟大量的線程,會占用大量的內存空間,降低程序的性能
2、線程越多,CPU在調度線程上的開銷就越大
3、程序設計更加復雜:比如線程之間的通信、多線程的數據共享
6、多線程的生命周期
線程狀態:
與人有生老病死一樣,線程也同樣要經歷新建、就緒、運行(活動)、阻塞和死亡五種不同的狀態。這五種狀態都可以通過Thread類中的方法進行控制。
創建並運行線程:
① 新建狀態(New Thread):在Java語言中使用new 操作符創建一個線程后,該線程僅僅是一個空對象,它具備類線程的一些特征,但此時系統沒有為其分配資源,這時的線程處於創建狀態。
線程處於創建狀態時,可通過Thread類的方法來設置各種屬性,如線程的優先級(setPriority)、線程名(setName)和線程的類型(setDaemon)等。
② 就緒狀態(Runnable):使用start()方法啟動一個線程后,系統為該線程分配了除CPU外的所需資源,使該線程處於就緒狀態。此外,如果某個線程執行了yield()方法,那么該線程會被暫時剝奪CPU資源,重新進入就緒狀態。
③ 運行狀態(Running):Java運行系統通過調度選中一個處於就緒狀態的線程,使其占有CPU並轉為運行狀態。此時,系統真正執行線程的run()方法。
a) 可以通過Thread類的isAlive方法來判斷線程是否處於就緒/運行狀態:當線程處於就緒/運行狀態時,isAlive返回true,當isAlive返回false時,可能線程處於阻塞狀態,也可能處於停止狀態。
④ 阻塞和喚醒線程
阻塞狀態(Blocked):一個正在運行的線程因某些原因不能繼續運行時,就進入阻塞 狀態。這些原因包括:
- 等待阻塞:當線程執行了某個對象的wait()方法時,線程會被置入該對象的等待集中,直到執行了該對象的notify()方法wait()/notify()方法的執行要求線程首先獲得該對象的鎖。
- 同步阻塞:當多個線程試圖進入某個同步區域(同步鎖)時,沒能進入該同步區域(同步鎖)的線程會被置入鎖定集(鎖池)中,直到獲得該同步區域的鎖,進入就緒狀態。
- 其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
⑤ 死亡狀態(Dead):線程在run()方法執行結束后進入死亡狀態。此外,如果線程執行了interrupt()或stop()方法,那么它也會以異常退出的方式進入死亡狀態。
7、終止線程的三種方法
① 使用退出標志,使線程正常退出,也就是當run方法完成后線程終止,推薦使用。
② 使用stop方法強制終止線程(這個方法不推薦使用,因為stop和suppend、resume一樣,也可能發生不可預料的結果)。
③ 使用interrupt方法中斷線程。