JAVA基础整理-100.Java 多线编程
Java線程的概念:什么是線程?
Windows 系統(tǒng)是多任務(wù)操作系統(tǒng),它以進(jìn)程為單位。
系統(tǒng)可以分配給每個進(jìn)程一段有限的執(zhí)行 CPU 的時間(也稱為 CPU 時間片
單任務(wù)的特點(diǎn)就是排隊執(zhí)行,也就是同步,就像在 cmd 中輸入一條命令后,必須等待這條命令執(zhí)行完才可以執(zhí)行下一條命令一樣。這就是單任務(wù)環(huán)境的缺點(diǎn),即 CPU 利用率大幅降低。
圖2 單線程和多線程執(zhí)行模式 線程可以理解成是在進(jìn)程中獨(dú)立運(yùn)行的子任務(wù)
Java多線程的實(shí)現(xiàn)方式
實(shí)現(xiàn)多線程編程的方式主要有兩種:一種是繼承 Thread 類,另一種是實(shí)現(xiàn) Runnable 接口。
繼承 Thread 類
使用繼承 Thread 類的方式實(shí)現(xiàn)多線程,最大的局限就是不支持多繼承
在使用多線程技術(shù)時,代碼的運(yùn)行結(jié)果與代碼執(zhí)行順序或調(diào)用順序是無關(guān)的。
除了異步調(diào)用之外,同步執(zhí)行線程 start() 方法的順序不代表線程啟動的順序。
實(shí)現(xiàn) Runnable 接口
如果要創(chuàng)建的線程類已經(jīng)有一個父類,這時就不能再繼承 Thread 類
提示:從 JDK 的 API 中可以發(fā)現(xiàn),實(shí)質(zhì)上 Thread 類實(shí)現(xiàn)了 Runnable 接口,其中的 run() 方法正是對 Runnable 接口中 run() 方法的具體實(shí)現(xiàn)。
圖1 使用Runnable接口啟動線程流程
要啟動一個新的線程,不是直接調(diào)用 Thread? 子類對象的 run() 方法,而是調(diào)用 Thread 子類的 start() 方法
?
兩種方法的比較
1. 繼承 Thread 類的優(yōu)缺點(diǎn)
而是可以簡單地使用 Threadsleep() 方法,繼承 Thread 類的方式使代碼變得簡單易讀。
2. 實(shí)現(xiàn) Runnable 接口的優(yōu)缺點(diǎn)
Thread 類是一個虛擬處理機(jī)嚴(yán)格的封裝,因此只有當(dāng)處理機(jī)模型修改或擴(kuò)展時,才應(yīng)該繼承該類。由于 Java 技術(shù)只允許單一繼承,因此如果已經(jīng)繼承了 Thread 類,就不能再繼承其他任何類,這會使用戶只能采用實(shí)現(xiàn) Runnable 接口的方式創(chuàng)建線程。
Java線程的生命周期及線程的幾種狀態(tài)
線程也具有生命周期,主要包括 7 種狀態(tài),分別是出生狀態(tài)、就緒狀態(tài)、運(yùn)行狀態(tài)、等待狀態(tài)、休眠狀態(tài)、阻塞狀態(tài)和死亡狀態(tài),
下面對線程生命周期中的 7 種狀態(tài)做說明。
提示:一旦線程進(jìn)入可執(zhí)行狀態(tài),它會在就緒狀態(tài)與運(yùn)行狀態(tài)下輾轉(zhuǎn),同時也可能進(jìn)入等待狀態(tài)、休眠狀態(tài)、阻塞狀態(tài)或死亡狀態(tài)。
Java多線程之間訪問實(shí)例變量
當(dāng)一個線程想要執(zhí)行同步方法里面的代碼時,線程首先嘗試去拿這把鎖,如果能夠拿到鎖,那么這個線程就可以執(zhí)行 synchronize 里面的代碼。如果不能拿到鎖,那么這個線程就會不斷地嘗試拿鎖,直到能夠拿到為止,而且有多個線程同時去爭搶這把鎖。
Java非線程安全問題的解決方法
非線程安全主要是指多個線程對同一個對象中的同一個實(shí)例變量進(jìn)行操作時會出現(xiàn)值被更改、值不同步的情況,進(jìn)而影響程序的執(zhí)行流程。
使用 synchronized 關(guān)鍵字修飾?doPost()?方法,即不允許多個線程同時修改?doPost()?方法中的變量。
Java多線程的同步機(jī)制:synchronized
所謂同步機(jī)制,指的是兩個線程同時作用在一個對象上,應(yīng)該保持對象數(shù)據(jù)的統(tǒng)一性和整體性。Java?提供 synchronized 關(guān)鍵字,為防止資源沖突提供了內(nèi)置支持。共享資源一般是文件、輸入/輸出端口或打印機(jī)。
synchronized 不僅可以用到同步方法,也可以用到同步塊。對于同步塊,synchronized 獲取的是參數(shù)中的對象鎖。
必須注意的是,Obj 對象的作用范圍不同,控制情況也不盡相同
Java curentThread()方法的作用
從結(jié)果可以發(fā)現(xiàn),雖然 this.getName() 方法返回的都是 Thread-0,但是在構(gòu)造方法中使用的即是 main 線程,而在 run() 方法中使用的是 A 線程。
Java isAlive()方法的作用
isAlive() 方法的作用是判斷當(dāng)前的線程是否處于活動狀態(tài)。
?
Java sleep方法的作用(sleep())
sleep() 方法的作用是在指定的毫秒數(shù)內(nèi)讓當(dāng)前“正在執(zhí)行的線程”休眠(暫停執(zhí)行)
Java getId()方法的作用
getId() 方法的作用非常簡單,就是取得正在運(yùn)行線程的唯一標(biāo)識
Java yieId()方法如何使用
yieId() 方法的作用是放棄當(dāng)前的 CPU 資源,將它讓給其他的任務(wù)去占用 CPU 執(zhí)行時間。
Java停止(終止)線程詳解版
停止一個線程意味著在線程處理完任務(wù)之前停掉正在做的操作,也就是放棄當(dāng)前的操作。
在 Java 中有以下 3 種方法可以終止正在運(yùn)行的線程:
停止不了的線程
interrupt() 方法的作用是用來停止線程,但 intermpt() 方法的使用效果并不像循環(huán)結(jié)構(gòu)中 break 語句那樣,可以馬上停止循環(huán)。
?
判斷線程是不是停止?fàn)顟B(tài)
intermpted() 方法具有清除狀態(tài)的功能,所以第二次調(diào)用 interrupted() 方法返回的值是 false。
異常法停止線程
就可在線程中用 for 語句來判斷線程是否為停止?fàn)顟B(tài),如果是停止?fàn)顟B(tài),則后面的代碼不再運(yùn)行。
在休眠中停止
從運(yùn)行結(jié)果來看,如果在休眠狀態(tài)下停止某一線程則會拋出進(jìn)入 InterruptedException 異常,所以會進(jìn)入 catch 語句塊清除停止?fàn)顟B(tài)值,使之變成 false。
強(qiáng)制停止線程
調(diào)用 stop() 方法可以在任意情況下強(qiáng)制停止一個線程。
注意:調(diào)用 stop() 方法時會拋出 java.lang.ThreadDeath 異常,但在通常情況下,此異常不需要顯式地捕捉。
釋放鎖的不良后果
使用 stop() 釋放鎖將會給數(shù)據(jù)造成不一致性的結(jié)果。
使用 return 停止線程
除了上面介紹的方法外,還可以將 intermpt() 方法與 return 結(jié)合使用來實(shí)現(xiàn)停止線程的效果。
Java暫停/掛起線程(suspend())和恢復(fù)線程
(resume())
在?Java?多線程中,可以使用 suspend() 方法暫停線程,使用 resume() 方法恢復(fù)線程的執(zhí)行。
suspend() 與 resume() 方法
從輸出結(jié)果的時間來看,調(diào)用 suspend() 方法確實(shí)可以暫停線程,而在調(diào)用 resume() 方法后線程恢復(fù)運(yùn)行狀態(tài)。
獨(dú)占問題
在使用 suspend() 方法與 resume() 方法時,如果使用不當(dāng)極易造成公共的同步對象被獨(dú)占,從而使得其他線程無法訪問公共同步對象。
不同步問題
在使用 suspend() 方法與 resume() 方法時也容易出現(xiàn)因?yàn)榫€程的暫停而導(dǎo)致數(shù)據(jù)不同步的情況。
?
Java線程的優(yōu)先級和執(zhí)行順序
優(yōu)先級概述
在 Java 語言中,線程的優(yōu)先級范圍是 1~10,值必須在 1~10,否則會出現(xiàn)異常;優(yōu)先級的默認(rèn)值為 5。優(yōu)先級較高的線程會被優(yōu)先執(zhí)行,當(dāng)執(zhí)行完畢,才會輪到優(yōu)先級較低的線程執(zhí)行。如果優(yōu)先級相同,那么就采用輪流執(zhí)行的方式。
可以使用 Thread 類中的 setPriority() 方法來設(shè)置線程的優(yōu)先級。語法如下:
public final void setPriority(int newPriority)
如果要獲取當(dāng)前線程的優(yōu)先級,可以直接調(diào)用 getPriority() 方法。語法如下: public final int getPriority();使用優(yōu)先級
?
轉(zhuǎn)載于:https://www.cnblogs.com/luojie1216/p/10621318.html
總結(jié)
以上是生活随笔為你收集整理的JAVA基础整理-100.Java 多线编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 架构设计之「服务限流」
- 下一篇: Java多线程——线程的优先级和生命周期