日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中therad_java中Thread的深入了解(一)

發布時間:2024/10/12 java 81 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中therad_java中Thread的深入了解(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程

線程是進程中的一個單一順序的執行單元,也被稱為輕量進程(lightweight process)。線程有自己的必須資源,同時與其他線程進程共享全部資源。同一個進程中,線程是并發執行的。由于線程的之間的相互制約,線程有就緒、阻塞、運行、結束等狀態。

一 新建線程

我們先創建兩個線程類:

新建一個MyThread類 繼承 Thread來覆蓋 run方法:

MyThread類

新建MyRunnable類 實現Runnable 接口:

MyRunable類

創建以及執行兩個線程類

主線程Main

線程結果

二 驗證線程并發

在上述創建的MyThread類和MyRunnable類各自的run方法輸出上 加個for循環for(int i=0;i<10000;i++);

循環線程

輸出結果extends

如果是順序執行,應該會是 extendsThread全部輸出完 ,才輸出implement thread。但是這并不是而是出現交叉結果 證明線程是并發執行。

交叉原理就是每個代碼 在cpu時間片內執行一段時間,到時間就換一個代碼 在cpu時間片內執行,但是如果時間片內打印完了,就看不見交叉現象。

單核cpu

三 線程聲明周期(或者線程狀態)

java中線程基本上有以下圖片中的幾種狀態:

線程狀態

首先我們要做一個輸出線程狀態的類:

線程狀態public static void printThreadState(Thread thread){

Thread.State state=thread.getState();

switch(state){

//1.新建狀態

caseNEW:

info(thread.getName()+" state is NEW");break;

//2.執行狀態

case RUNNABLE:

info(thread.getName()+" state is RUNNABLE");break;

//3.等待超時狀態

case TIMED_WAITING:

console.info(thread.getName()+" state is TIMED_WAITING");break;

//4.等待狀態

case WAITING:

info(thread.getName()+" state is WAITING");break;

//5.阻塞狀態

case BLOCKED:

info(thread.getName()+" state is BLOCKED");break;

//6.結束狀態

caseTERMINATED:

info(thread.getName()+" state is TERMINATED");break;

default:

info

(thread.getName()+" state is UNKOWN");

}

}

//打印

public static? void info(Object o){

System.out.println(String.valueOf(o));

}

1.新建狀態:

new之后 start之前都屬于NEW狀態,一旦狀態變成其他,則不會再變成NEW狀態。public static? void main(String args[]) throws InterruptedException{

Thread t=new Thread(new Runnable() {

@Override

public void run() {

}

});

printThreadState(t);//查看new之后的thread狀態

}

2.執行狀態

在run()方法里的時候,線程處于執行狀態。一旦run()方法執行完畢,則狀態就不是執行狀態了

執行狀態

線程狀態輸出結果

3.等待超時狀態

當調用wait(long timeout)方法的時候,線程處于等待狀態,并且超時后并不馬上返回,而是等待獲取鎖后返回。

查看wait(long timeout)

輸出結果

驗證超時后并不馬上返回,而是等待獲取鎖后返回。

添加一條輸出結果

如果是wait(long timeout)方法時候,提前先把鎖獲取過來等待20s

會發現輸出結果線程還是阻塞狀態

所以我們會發現一個問題,wait的超時只是一個預想, 多少時間后我再去獲取鎖,如果拿到就返回 拿不到就處于等待狀態。這里就會發現這里等待是最少需要long timeout時間。

wait(等多少時間后 再去競爭鎖),wait的時間內 我不去競爭 跟別人搶鎖,所以這個時間 不保證鎖一定能搶回來。

注意:Thread.sleep 也會進入TIME_WAITING狀態。

5.等待狀態

wait()睡眠不參與搶鎖,等待notify來進行喚醒。

放棄搶鎖,處于waiting狀態

waiting狀態時候喚醒

輸出結果

wait 也可以通過interrupt喚醒,interrupt是中斷線程的方法。

5.阻塞狀態

如果獲取不到鎖,就一直在阻塞狀態,直到獲取鎖為止。

把循環鎖死,當狀態位鎖死的時候釋放鎖

輸出結果

6.結束狀態

在run()方法執行結束以后,線程處于結束狀態

結束狀態

但是當這個線程執行結束了之后,是否代表這個線程被銷毀了呢。然而只是線程執行單元銷毀了,但是線程對象還在。雖然這個線程對象還存在,但是它已經不能進行再次的start()方法進行執行了。

四 研究多線程鎖問題

經典并發問題:當運行一萬個線程想List插入的時候,預期結果是有10000個,但是輸出確不是10000個,而是少于1000個。原因是 線程并發執行獲取list的長度是過期的。

比如我拿到list ,你也拿到list ,咱倆同時看list里有1條數據 我把數據插入第二個位置 ,你也插入第二個位置 ,就會導致list最終結果只有2條數據,實際上插入了3條數據。public static void ThreadMuliteTest() throws InterruptedException {

final?List?list=new?ArrayList();

for(int?i=0;i<10000;i++){

new?Thread(new?Runnable()?{

@Override

public?void?run()?{

list.add(Thread.currentThread().getName());

}

}).start();

}

Thread.sleep(1000);

System.out.println(list.size());

}

輸出結果

這就是線程并發問題,并發問題有個解決辦法 就是對線程進行枷鎖讓他排隊,我拿到了 你就不能拿。

synchronized 代碼段是java給線程的一個控制權,可以鎖住一個資源,防止被其他人用。加鎖之后線程就進入了 排隊狀態 ,只有一個線程能拿到list的權限 其他等待。

還有一種操作 就是我得到資源后 ,可以釋放一段時間給別人用 ,超時了 我在拿回來自己用。public static void ThreadGetWait() throws InterruptedException {

Object lock=new Object();

new Thread(new Runnable() {

@Override

public void run() {

synchronized (lock){

console.info("線程一:拿到鎖");

try {

lock.wait(100);//釋放100ms

} catch (InterruptedException e) {

e.printStackTrace();

}

console.info("線程一:鎖又被我拿回來了");

try {

Thread.sleep(1000);//睡1s 鎖不給別人

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

Thread.sleep(10);//休眠10ms防止第二個線程拿到鎖

new Thread(new Runnable() {

@Override

public void run() {

synchronized (lock){

console.info("線程二:拿到鎖");

try {

Thread.sleep(2000);//拿到鎖后我要休眠2s

} catch (InterruptedException e) {

e.printStackTrace();

}

console.info("線程二:鎖又回來了?");

}

}

}).start();

}

輸出結果

因為線程1先運行 肯定拿到鎖,線程一暫時釋放。所以線程二緊接著拿到了鎖,線程二休眠了2s 期間并沒有釋放鎖,所以線程1一直處于阻塞狀態,線程二執行完成后 釋放鎖 線程一 打印 最后一句。

總結

以上是生活随笔為你收集整理的Java中therad_java中Thread的深入了解(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。