Java 多線(xiàn)程實(shí)例詳解(二)
本文承接上一篇文章《Java多線(xiàn)程實(shí)例詳解(一)》。
四.Java多線(xiàn)程的阻塞狀態(tài)與線(xiàn)程控制
上文已經(jīng)提到Java阻塞的幾種具體類(lèi)型。下面分別看下引起Java線(xiàn)程阻塞的主要方法。
1.join()
join —— 讓一個(gè)線(xiàn)程等待另一個(gè)線(xiàn)程完成才繼續(xù)執(zhí)行。如A線(xiàn)程線(xiàn)程執(zhí)行體中調(diào)用B線(xiàn)程的join()方法,則A線(xiàn)程被阻塞,知道B線(xiàn)程執(zhí)行完為止,A才能得以繼續(xù)執(zhí)行。
public class ThreadTest {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
thread.start();
try {
thread.join(); // main線(xiàn)程需要等待thread線(xiàn)程執(zhí)行完后才能繼續(xù)執(zhí)行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
2.sleep()
sleep —— 讓當(dāng)前的正在執(zhí)行的線(xiàn)程暫停指定的時(shí)間,并進(jìn)入阻塞狀態(tài)。在其睡眠的時(shí)間段內(nèi),該線(xiàn)程由于不是處于就緒狀態(tài),因此不會(huì)得到執(zhí)行的機(jī)會(huì)。即使此時(shí)系統(tǒng)中沒(méi)有任何其他可執(zhí)行的線(xiàn)程,出于sleep()中的線(xiàn)程也不會(huì)執(zhí)行。因此sleep()方法常用來(lái)暫停線(xiàn)程執(zhí)行。
前面有講到,當(dāng)調(diào)用了新建的線(xiàn)程的start()方法后,線(xiàn)程進(jìn)入到就緒狀態(tài),可能會(huì)在接下來(lái)的某個(gè)時(shí)間獲取CPU時(shí)間片得以執(zhí)行,如果希望這個(gè)新線(xiàn)程必然性的立即執(zhí)行,直接調(diào)用原來(lái)線(xiàn)程的sleep(1)即可。
public class ThreadTest {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
thread.start();
try {
Thread.sleep(1); // 使得thread必然能夠馬上得以執(zhí)行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
注:睡一個(gè)毫秒級(jí)夠了,因?yàn)镃PU不會(huì)空閑,會(huì)切換到新建的線(xiàn)程。
3.后臺(tái)線(xiàn)程(Daemon Thread)
概念/目的:后臺(tái)線(xiàn)程主要是為其他線(xiàn)程(相對(duì)可以稱(chēng)之為前臺(tái)線(xiàn)程)提供服務(wù),或“守護(hù)線(xiàn)程”。如JVM中的垃圾回收線(xiàn)程。
生命周期:后臺(tái)線(xiàn)程的生命周期與前臺(tái)線(xiàn)程生命周期有一定關(guān)聯(lián)。主要體現(xiàn)在:當(dāng)所有的前臺(tái)線(xiàn)程都進(jìn)入死亡狀態(tài)時(shí),后臺(tái)線(xiàn)程會(huì)自動(dòng)死亡(其實(shí)這個(gè)也很好理解,因?yàn)楹笈_(tái)線(xiàn)程存在的目的在于為前臺(tái)線(xiàn)程服務(wù)的,既然所有的前臺(tái)線(xiàn)程都死亡了,那它自己還留著有什么用...偉大啊 ! !)。
設(shè)置后臺(tái)線(xiàn)程:調(diào)用Thread對(duì)象的setDaemon(true)方法可以將指定的線(xiàn)程設(shè)置為后臺(tái)線(xiàn)程。
public class ThreadTest {
public static void main(String[] args) {
Thread myThread = new MyThread();
for (int i = 0; i < 100; i++) {
System.out.println("main thread i = " + i);
if (i == 20) {
myThread.setDaemon(true);
myThread.start();
}
}
}
}
class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
判斷線(xiàn)程是否是后臺(tái)線(xiàn)程:調(diào)用thread對(duì)象的isDeamon()方法。
注:main線(xiàn)程默認(rèn)是前臺(tái)線(xiàn)程,前臺(tái)線(xiàn)程創(chuàng)建中創(chuàng)建的子線(xiàn)程默認(rèn)是前臺(tái)線(xiàn)程,后臺(tái)線(xiàn)程中創(chuàng)建的線(xiàn)程默認(rèn)是后臺(tái)線(xiàn)程。調(diào)用setDeamon(true)方法將前臺(tái)線(xiàn)程設(shè)置為后臺(tái)線(xiàn)程時(shí),需要在start()方法調(diào)用之前。前天線(xiàn)程都死亡后,JVM通知后臺(tái)線(xiàn)程死亡,但從接收指令到作出響應(yīng),需要一定的時(shí)間。
4.改變線(xiàn)程的優(yōu)先級(jí)/setPriority():
每個(gè)線(xiàn)程在執(zhí)行時(shí)都具有一定的優(yōu)先級(jí),優(yōu)先級(jí)高的線(xiàn)程具有較多的執(zhí)行機(jī)會(huì)。每個(gè)線(xiàn)程默認(rèn)的優(yōu)先級(jí)都與創(chuàng)建它的線(xiàn)程的優(yōu)先級(jí)相同。main線(xiàn)程默認(rèn)具有普通優(yōu)先級(jí)。
設(shè)置線(xiàn)程優(yōu)先級(jí):setPriority(int priorityLevel)。參數(shù)priorityLevel范圍在1-10之間,常用的有如下三個(gè)靜態(tài)常量值:
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
獲取線(xiàn)程優(yōu)先級(jí):getPriority()。
注:具有較高線(xiàn)程優(yōu)先級(jí)的線(xiàn)程對(duì)象僅表示此線(xiàn)程具有較多的執(zhí)行機(jī)會(huì),而非優(yōu)先執(zhí)行。
public class ThreadTest {
public static void main(String[] args) {
Thread myThread = new MyThread();
for (int i = 0; i < 100; i++) {
System.out.println("main thread i = " + i);
if (i == 20) {
myThread.setPriority(Thread.MAX_PRIORITY);
myThread.start();
}
}
}
}
class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
}
}
5.線(xiàn)程讓步:yield()
上一篇博文中已經(jīng)講到了yield()的基本作用,同時(shí),yield()方法還與線(xiàn)程優(yōu)先級(jí)有關(guān),當(dāng)某個(gè)線(xiàn)程調(diào)用yiled()方法從運(yùn)行狀態(tài)轉(zhuǎn)換到就緒狀態(tài)后,CPU從就緒狀態(tài)線(xiàn)程隊(duì)列中只會(huì)選擇與該線(xiàn)程優(yōu)先級(jí)相同或優(yōu)先級(jí)更高的線(xiàn)程去執(zhí)行。
public class ThreadTest {
public static void main(String[] args) {
Thread myThread1 = new MyThread1();
Thread myThread2 = new MyThread2();
myThread1.setPriority(Thread.MAX_PRIORITY);
myThread2.setPriority(Thread.MIN_PRIORITY);
for (int i = 0; i < 100; i++) {
System.out.println("main thread i = " + i);
if (i == 20) {
myThread1.start();
myThread2.start();
Thread.yield();
}
}
}
}
class MyThread1 extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("myThread 1 -- i = " + i);
}
}
}
class MyThread2 extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("myThread 2 -- i = " + i);
}
}
}
系列文章:
java 多線(xiàn)程實(shí)例講解 (一)
Java 多線(xiàn)程實(shí)例詳解(二)
Java 多線(xiàn)程實(shí)例詳解(三)
- Java 多線(xiàn)程實(shí)例講解(一)
- Java Thread多線(xiàn)程詳解及用法解析
- Java 多線(xiàn)程學(xué)習(xí)詳細(xì)總結(jié)
- java 線(xiàn)程創(chuàng)建多線(xiàn)程詳解
- java多線(xiàn)程-同步塊實(shí)例講解
- java 多線(xiàn)程-線(xiàn)程通信實(shí)例講解
- java 多線(xiàn)程-鎖詳解及示例代碼
- java多線(xiàn)程-讀寫(xiě)鎖原理
- Java多線(xiàn)程之異步Future機(jī)制的原理和實(shí)現(xiàn)
- Java 多線(xiàn)程實(shí)例詳解(三)
相關(guān)文章
淺析Java中StringBuffer和StringBuilder的使用
當(dāng)對(duì)字符串進(jìn)行修改的時(shí)候,需要使用 StringBuffer 和 StringBuilder 類(lèi)。本文就來(lái)和大家簡(jiǎn)單聊聊這二者的使用與區(qū)別吧,希望對(duì)大家有所幫助2023-04-04
基于jenkins構(gòu)建結(jié)果企業(yè)微信提醒
這篇文章主要介紹了基于jenkins構(gòu)建結(jié)果企業(yè)微信提醒,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
詳解如何獲取java中類(lèi)的所有對(duì)象實(shí)例
如何在運(yùn)行時(shí)獲取一個(gè)Java類(lèi)的所有對(duì)象實(shí)例呢,本文給大家介紹一種底層實(shí)現(xiàn)的方式,基于jvmti,代碼用C++實(shí)現(xiàn),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10
Gradle的SpringBoot項(xiàng)目構(gòu)建圖解
這篇文章主要介紹了Gradle的SpringBoot項(xiàng)目構(gòu)建圖解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

