Thread 线程同步、线程状态
線程概念
線程(英語:thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。
一、多線程介紹
1.1創(chuàng)建線程類
Java中通過繼承Thread類來創(chuàng)建并啟動(dòng)多線程的步驟如下:
1.定義Thread類的子類,并重寫該類的run()方法,該run()方法的方法體就代表了線程需要完成的任務(wù),因此把run()方法稱為線程執(zhí)行體。
2. 創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建了線程對(duì)象
3. 調(diào)用線程對(duì)象的start()方法來啟動(dòng)該線程
測(cè)試類:
public class ThreadIdea {
public static void main(String[] args) {
subThread th=new subThread();
th.start();
for (int i = 0; i < 200; i++) {
System.out.println(Thread.currentThread().getName()+" 主線程被執(zhí)行"+i+“次”);
}
}
}
自定義線程類:
public class subThread extends Thread{
@Override
public void run() {//重寫run方法
for (int i = 0; i < 200; i++) {
System.out.println(Thread.currentThread().getName()+" 子線程被執(zhí)行"+i+“次”);
}
}
}
二、多線程的原理
2.1多線程的原理
代碼同上
2.2Thread類
操作過程中用到了java.lang.Thread類
1.構(gòu)造方法:
public Thread():分配一個(gè)新的線程對(duì)象。
public Thread(String name):分配一個(gè)指定名字的新的線程對(duì)象。
public Thread(Runnable target):分配一個(gè)帶有指定目標(biāo)新的線程對(duì)象。
public Thread(Runnable target,String name):分配一個(gè)帶有指定目標(biāo)新的線程對(duì)象并指定名字。
2常用方法:
public String getName():獲取當(dāng)前線程名稱。
public void start():導(dǎo)致此線程開始執(zhí)行; Java虛擬機(jī)調(diào)用此線程的run方法。
public void run():此線程要執(zhí)行的任務(wù)在此處定義代碼。
public static void sleep(long millis):使當(dāng)前正在執(zhí)行的線程以指定的毫秒數(shù)暫停(暫時(shí)停止執(zhí)行)。
public static Thread currentThread():返回對(duì)當(dāng)前正在執(zhí)行的線程對(duì)象的引用。
翻閱API后得知?jiǎng)?chuàng)建線程的方式總共有兩種,一種是繼承Thread類方式,一種是實(shí)現(xiàn)Runnable接口方式,方式一我們上一天已經(jīng)完成,接下來講解方式二實(shí)現(xiàn)的方式。
2.3 實(shí)現(xiàn)接口方式
采用java.lang.Runnable也是非常常見的一種,我們只需要重寫run方法即可。
步驟如下:
1.定義Runnable接口的實(shí)現(xiàn)類,并重寫該接口的run()方法,該run()方法的方法體同樣是該線程的線程執(zhí)行體。
2.創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此實(shí)例作為Thread的target來創(chuàng)建Thread對(duì)象,該Thread對(duì)象才是真正的線程對(duì)象。
3.調(diào)用線程對(duì)象的start()方法來啟動(dòng)線程。代碼如下:
測(cè)試類代碼:
public class test {
public static void main(String[] args) {
runnable runa=new runnable();
Thread th=new Thread(runa);
th.start();
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+" 主線程被調(diào)用");
}
}
}
Runnable接口代碼:
public class runnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+" 子線程被調(diào)用"+i);
}
}
}
通過實(shí)現(xiàn)Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程序的一個(gè)執(zhí)行目標(biāo)。所有的多線程代碼都在run方法里面。Thread類實(shí)際上也是實(shí)現(xiàn)了Runnable接口的類。
在啟動(dòng)的多線程的時(shí)候,需要先通過Thread類的構(gòu)造方法Thread(Runnable target) 構(gòu)造出對(duì)象,然后調(diào)用Thread對(duì)象的start()方法來運(yùn)行多線程代碼。//代碼中沒體現(xiàn)構(gòu)造Thread這一點(diǎn)
實(shí)際上所有的多線程代碼都是通過運(yùn)行Thread的start()方法來運(yùn)行的。因此,不管是繼承Thread類還是實(shí)現(xiàn)Runnable接口來實(shí)現(xiàn)多線程,最終還是通過Thread的對(duì)象的API來控制線程的,熟悉Thread類的API是進(jìn)行多線程編程的基礎(chǔ)。
Thread和Runnable的區(qū)別
如果一個(gè)類繼承Thread,則不適合資源共享。但是如果實(shí)現(xiàn)了Runable接口的話,則很容易的實(shí)現(xiàn)資源共享。
總結(jié):
實(shí)現(xiàn)Runnable接口比繼承Thread類所具有的優(yōu)勢(shì):
1.適合多個(gè)相同的程序代碼的線程去共享同一個(gè)資源。
2.可以避免java中的單繼承的局限性。
3.增加程序的健壯性,實(shí)現(xiàn)解耦操作,代碼可以被多個(gè)線程共享,代碼和線程獨(dú)立。
4.線程池只能放入實(shí)現(xiàn)Runable或Callable類線程,不能直接放入繼承Thread的類。
2.4 匿名內(nèi)部類方式
使用匿名內(nèi)部類的方式實(shí)現(xiàn)Runnable接口,重新Runnable接口中的run方法:
public class anonymousInsideClass {
public static void main(String[] args) {
new Thread(new runnable(){
@Override
public void run() {
System.out.println(“使用匿名內(nèi)部類線程”);
}
}).start();
//相當(dāng)于
Thread th= new Thread();
runnable runmethond=new runnable(){
@Override
public void run() {
System.out.println(“使用匿名內(nèi)部類線程”);
}
};
new Thread(runmethond).start();
}
}
三、線程安全
3.1 線程安全
3.2 線程同步
當(dāng)我們使用多個(gè)線程訪問同一資源的時(shí)候,且多個(gè)線程中對(duì)資源有寫的操作,就容易出現(xiàn)線程安全問題。要解決上述多線程并發(fā)訪問一個(gè)資源的安全性問題:也就是解決重復(fù)票與不存在票問題,Java中提供了同步機(jī)制(synchronized)來解決。
為了保證每個(gè)線程都能正常執(zhí)行原子操作,Java引入了線程同步機(jī)制。那么怎么去使用呢?有三種方式完成同步操作:
同步代碼塊。同步方法。鎖機(jī)制。
3.3 同步代碼塊
同步代碼塊:synchronized關(guān)鍵字可以用于方法中的某個(gè)區(qū)塊中,表示只對(duì)這個(gè)區(qū)塊的資源實(shí)行互斥訪問。
格式:
synchronized(同步鎖){
需要同步操作的代碼
}
同步鎖:
對(duì)象的同步鎖只是一個(gè)概念,可以想象為在對(duì)象上標(biāo)記了一個(gè)鎖.
鎖對(duì)象 可以是任意類型。
多個(gè)線程對(duì)象 要使用同一把鎖。
同步方法
同步方法:使用synchronized修飾的方法,就叫做同步方法,保證A線程執(zhí)行該方法的時(shí)候,其他線程只能在方法外等著。
3.5 Lock鎖
java.util.concurrent.locks.Lock機(jī)制提供了比synchronized代碼塊和synchronized方法更廣泛的鎖定操作,同步代碼塊/同步方法具有的功能Lock都有,除此之外更強(qiáng)大,更體現(xiàn)面向?qū)ο蟆?br /> Lock鎖也稱同步鎖,加鎖與釋放鎖方法化了,如下:
public void lock():加同步鎖。
public void unlock():釋放同步鎖。
四、線程的狀態(tài)
NEW(新建)
線程剛被創(chuàng)建,但是并未啟動(dòng)。還沒調(diào)用start方法。Runnable(可運(yùn)行)線程可以在java虛擬機(jī)中運(yùn)行的狀態(tài),可能正在運(yùn)行自己代碼,也可能沒有,這取決于操作系統(tǒng)處理器。
Blocked(鎖阻塞)
當(dāng)一個(gè)線程試圖獲取一個(gè)對(duì)象鎖,而該對(duì)象鎖被其他的線程持有,則該線程進(jìn)入Blocked狀態(tài);當(dāng)該線程持有鎖時(shí),該線程將變成Runnable狀態(tài)。
Waiting(無限等待)
一個(gè)線程在等待另一個(gè)線程執(zhí)行一個(gè)(喚醒)動(dòng)作時(shí),該線程進(jìn)入Waiting狀態(tài)。進(jìn)入這個(gè)狀態(tài)后是不能自動(dòng)喚醒的,必須等待另一個(gè)線程調(diào)用notify或者notifyAll方法才能夠喚醒。
Timed Waiting(計(jì)時(shí)等待)
同waiting狀態(tài),有幾個(gè)方法有超時(shí)參數(shù),調(diào)用他們將進(jìn)入Timed Waiting狀態(tài)。這一狀態(tài)將一直保持到超時(shí)期滿或者接收到喚醒通知。帶有超時(shí)參數(shù)的常用方法有Thread.sleep 、Object.wait。
Teminated(被終止)
因?yàn)閞un方法正常退出而死亡,或者因?yàn)闆]有捕獲的異常終止了run方法而死亡。
總結(jié)
以上是生活随笔為你收集整理的Thread 线程同步、线程状态的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddos软件免费(ddos软件vip版)
- 下一篇: File类、递归、字节流