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

歡迎訪問 生活随笔!

生活随笔

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

java

Java核心(一)线程Thread详解

發布時間:2025/3/11 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java核心(一)线程Thread详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、概述

在開始學習Thread之前,我們先來了解一下 線程和進程之間的關系:

線程(Thread)是進程的一個實體,是CPU調度和分派的基本單位。 線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。 線程和進程的關系是:線程是屬于進程的,線程運行在進程空間內,同一進程所產生的線程共享同一內存空間,當進程退出時該進程所產生的線程都會被強制退出并清除。

由上描述,可以得知線程作為cpu的基本調度單位,只有把多線程用好,才能充分利用cpu的多核資源。

本文基于JDK 8(也可以叫JDK 1.8)。

二、線程使用

2.1 啟動線程

創建線程有四種方式:

  • 實現Runnable接口
  • 繼承Thread類
  • 使用JDK 8 的Lambda
  • 使用Callable和Future

2.1.1 Runnable創建方式

public class MyThread implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());} } Thread thread = new Thread(new MyThread()); thread.start();

2.1.2 繼承Thread創建方式

public class MyThread extends Thread{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());} } MyThread thread = new MyThread(); thread.start();

以上代碼有更簡單的寫法,如下:

Thread thread = new Thread(){@Overridepublic void run() {System.out.println(Thread.currentThread().getName());} }; thread.start();

2.1.3 Lambda創建方式

new Thread(()-> System.out.println(Thread.currentThread().getName())).start();

2.1.4 使用Callable和Future

看源碼可以知道Thread的父類是Runnable是JDK1.0提供的,而Callable和Runnable類似,是JDK1.5提供的,彌補了調用線程沒有返回值的情況,可以看做是Runnable的一個補充,下面看看Callable的實現。

public class MyThread implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println(Thread.currentThread().getName());return Thread.currentThread().getName();} } Callable<String> callable = new MyThread(); FutureTask<String> ft = new FutureTask<>(callable); new Thread(ft,"threadName").start(); System.out.println(ft.get());

2.1.5 run()和start()的區別

真正啟動線程的是start()方法而不是run(),run()和普通的成員方法一樣,可以重復使用,但不能啟動一個新線程。

2.2 Thread的常用方法

Thread類方法

方法說明
start()啟動線程
setName(String name)設置線程名稱
setPriority(int priority)設置線程優先級,默認5,取值1-10
join(long millisec)掛起線程xx毫秒,參數可以不傳
interrupt()終止線程
isAlive()測試線程是否處于活動狀態

Thread靜態(static)方法

方法說明
yield()暫停當前正在執行的線程對象,并執行其他線程。
sleep(long millisec)/sleep(long millis, int nanos)掛起線程xx秒,參數不可省略
currentThread()返回對當前正在執行的線程對象的引用
holdsLock(Object x)當前線程是否擁有鎖

2.3 sleep()和wait()的區別

sleep為線程的方法,而wait為Object的方法,他們的功能相似,最大本質的區別是:sleep不釋放鎖,wait釋放鎖。

用法上的不同:sleep(milliseconds)可以用時間指定來使他自動醒過來,如果時間不到你只能調用interreput()來終止線程;wait()可以用notify()/notifyAll()直接喚起。

重點: 測試wait和sleep釋放鎖的代碼如下:

public class SynchronizedTest extends Thread {int number = 10;public synchronized void first(){System.out.println("this is first!");number = number+1;}public synchronized void secord() throws InterruptedException {System.out.println("this is secord!!");Thread.sleep(1000); // this.wait(1000);number = number*100;}@Overridepublic void run() {first();} } SynchronizedTest synchronizedTest = new SynchronizedTest(); synchronizedTest.start(); synchronizedTest.secord(); // 主線程稍等10毫秒 Thread.sleep(10); System.out.println(synchronizedTest.number);

根據結果可以得知:

  • 執行sleep(1000)運行的結果是:1001
  • 執行wait(1000)運行的結果是:1100

總結: 使用 sleep(1000)不釋放同步鎖,執行的是10*100+1=1001,wait(1000)釋放了鎖,執行的順序是(10+1)x100=1100,所以sleep不釋放鎖,wait釋放鎖。

三、線程狀態

3.1 線程狀態概覽

線程狀態:

  • NEW 尚未啟動
  • RUNNABLE 正在執行中
  • BLOCKED 阻塞的(被同步鎖或者IO鎖阻塞)
  • WAITING 永久等待狀態
  • TIMED_WAITING 等待指定的時間重新被喚醒的狀態
  • TERMINATED 執行完成

線程的狀態可以使用getState()查看,更多狀態詳情,查看Thread源碼,如下圖:

3.2 線程的狀態代碼實現

3.2.1 NEW 尚未啟動狀態

Thread thread = new Thread() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());} }; // 只聲明不調用start()方法,得到的狀態是NEW System.out.println(thread.getState()); // NEW

3.2.2 RUNNABLE 運行狀態

Thread thread = new Thread() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());} }; thread.start(); System.out.println(thread.getState()); // RUNNABLE

3.2.3 BLOCKED 阻塞狀態

使用synchronized同步阻塞實現,代碼如下:

public class MyCounter {int counter;public synchronized void increase() {counter++;try {Thread.sleep(10*1000);} catch (InterruptedException e) {e.printStackTrace();}} } MyCounter myCounter = new MyCounter(); // 線程1調用同步線程,模擬阻塞 new Thread(()-> myCounter.increase()).start(); // 線程2繼續調用同步阻塞方法 Thread thread = new Thread(()-> myCounter.increase()); thread.start();// 讓主線程等10毫秒 Thread.currentThread().sleep(10); // 打印線程2,為阻塞狀態:BLOCKED System.out.println(thread.getState());

3.2.4 WAITING 永久等待狀態

public class MyThread extends Thread{@Overridepublic void run() {synchronized (MyThread.class){try {MyThread.class.wait();System.out.println(Thread.currentThread().getName());} catch (InterruptedException e) {e.printStackTrace();}}} } Thread thread = new Thread(new MyThread()); thread.start(); // 主線程掛起200毫秒,等thread執行完成 Thread.sleep(200); // 輸出WAITING,線程thread一直處于被掛起狀態 System.out.println(thread.getState());

喚醒線程: 可使用 notify/notifyAll 方法,代碼如下:

synchronized (MyThread.class) {MyThread.class.notify(); }

使線程WAITING的方法:

  • Object的wait() 不設置超時時間
  • Thread.join()不設置超時時間
  • LockSupport的park()

查看Thread源碼可以知道Thread的join方法,底層使用的是Object的wait實現的,如下圖:

注意: 查看Object的源碼可知wait(),不傳遞參數,等同于wait(0),設置的“0”不是立即執行,而是無限的等待,不執行,如下圖:

3.2.5 TIMED_WAITING 超時等待狀態

TIMED_WAITING狀態,只需要給wait設置上時間即可,代碼如下:

public class MyThread extends Thread{@Overridepublic void run() {synchronized (MyThread.class){try {MyThread.class.wait(1000);System.out.println(Thread.currentThread().getName());} catch (InterruptedException e) {e.printStackTrace();}}} }

調用代碼還是一樣的,如下:

Thread thread = new Thread(new MyThread()); thread.start(); // 主線程掛起200毫秒,等thread執行完成 Thread.sleep(200); // 輸出TIMED_WAITING System.out.println(thread.getState()); synchronized (MyThread.class) {MyThread.class.notify(); }

3.2.6 TERMINATED 完成狀態

Thread thread = new Thread(()-> System.out.println(Thread.currentThread().getName())); thread.start(); // 讓主線程等10毫秒 Thread.currentThread().sleep(10); System.out.println(thread.getState());

四、死鎖

根據前面的知識,我們知道使用sleep的時候是不釋放鎖的,所以利用這個特性我們可以很輕易的寫出死鎖的代碼,具體的流程如圖(圖片來源于楊曉峰老師文章):

代碼如下:

static Object object1 = new Object(); static Object object2 = new Object();public static void main(String[] args) {Thread thread = new Thread(){@Overridepublic void run() {synchronized (object1){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (object2){System.out.println(Thread.currentThread().getName());}}}};Thread thread2 = new Thread(){@Overridepublic void run() {synchronized (object2){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (object1){System.out.println(Thread.currentThread().getName());}}}};thread.start();thread2.start();

運行上面的代碼,程序會處于無限等待之中。

五、總結

根據上面的內容,我們已經系統的學習Thread的使用了,然而學而不思則罔,最后留一個思考題:根據本文介紹的知識,怎么能避免死鎖?

源碼下載:https://github.com/vipstone/java-core-example.git


參考文檔

Java核心技術36講:http://t.cn/EwUJvWA

https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html

總結

以上是生活随笔為你收集整理的Java核心(一)线程Thread详解的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 成人在线视频一区二区三区 | 中文字幕狠狠干 | 中文字幕av影院 | 麻豆综合| www国产免费 | 永久视频在线观看 | 91亚洲一区 | 小罗莉极品一线天在线 | 色婷在线| 无码人妻丰满熟妇区五十路 | 亚洲欧美精品午睡沙发 | 免费视频中文字幕 | 狠狠亚洲| 亚洲av永久无码精品 | 男女无遮挡网站 | 欧美另类视频在线观看 | 女人18毛片毛片毛片毛片区二 | 日韩中文一区 | 久久精品一区二区三区不卡牛牛 | av网址有哪些 | 亚洲第一色| 日本一区二区免费在线 | 99热3 | 强睡邻居人妻中文字幕 | 131mm少妇做爰视频 | 强开乳罩摸双乳吃奶羞羞www | 嫩草www | 性高潮视频在线观看 | 亚洲第一国产视频 | 亚洲人成无码www久久久 | 中文在线a√在线8 | 性囗交免费视频观看 | 亚洲免费视频观看 | 欧美午夜精品一区二区三区 | 精品免费在线观看 | 国产在线视频在线观看 | 国产美女福利视频 | 黄色免费在线网址 | 最近中文在线观看 | 国产精品50页| 99久久久无码国产精品免费 | 黄色www视频 | 天天av天天翘 | 91亚洲精选| 杨幂国产精品一区二区 | 精品在线免费视频 | 美女视频一区二区 | 亚洲午夜一区二区 | 96视频在线 | 国产一区二区免费 | 亚洲男性天堂 | 999成人网| 亚洲最大黄网 | 色婷婷av一区 | 波多野结衣视频网址 | 久久久久久久一区二区三区 | 国产综合视频一区 | 夜夜嗨av一区二区三区四区 | 私人av| 天天色天天搞 | 少女国产免费观看 | 人人艹人人爽 | 日韩av在线中文字幕 | 污视频在线免费观看 | aaaa级片 | 欧美人妻精品一区二区三区 | 成人在线免费电影 | 九九精品在线视频 | 亚洲 欧美 日韩系列 | 日本免费在线视频观看 | 日本天堂网在线 | 亚洲毛片精品 | 91色在线观看 | av资源在线免费观看 | 少妇真人直播免费视频 | 婷婷久久五月 | 日韩欧美中文字幕在线播放 | 国产一区二区三区影视 | 国产免费的av | 一级片在线观看视频 | 日本一区二区三区视频在线播放 | 亚洲成肉网 | 国产精品野外户外 | 在线观看视频一区 | 成年人的视频网站 | 综合热久久 | 日本高清网色 | 青草视频网 | 亚洲a视频 | 蜜桃无码一区二区三区 | 制中文字幕音影 | 少妇特黄a一区二区三区88av | 在线观看欧美亚洲 | 午夜在线观看视频 | 五月婷婷七月丁香 | 一本av在线 | 国产人人干 | 亚洲av成人精品日韩在线播放 | 日本精品一区在线 |