Java線程的控制詳解
1. join線程:
在線程執(zhí)行過程中,有時(shí)想讓另一個(gè)線程先執(zhí)行,比如將一大問題分割成許多小問題,給每一個(gè)小問題分配線程,但所有小問題處理完后再讓主線程進(jìn)一步操作。此時(shí)我們可以在主線程中調(diào)用其它線程的join()方法,以阻塞調(diào)用線程(在這里為主線程)。
示例代碼:
package org.frzh.thread;
public class JoinThread extends Thread{
//提供一個(gè)有參構(gòu)造器,用來設(shè)置線程的名字
public JoinThread(String name) {
super(name);
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args) {
//啟動(dòng)子線程
new JoinThread("新線程").start();
for (int i = 0; i < 100; i++) {
if (i == 20) {
JoinThread jt = new JoinThread("被join的線程");
jt.start();
//main線程調(diào)用了jt線程的join方法,則main線程必須等待jt執(zhí)行完之后才能執(zhí)行
try {
jt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " +i);
}
}
}
本來有三套線程(兩條子線程和一main線程),當(dāng)i=20后,main線程被阻塞必須等到“被join線程”執(zhí)行完之后才有機(jī)會(huì)執(zhí)行,所以此后只有兩條線程執(zhí)行。
join()方法的三種重載形式:
join():等待被join線程執(zhí)行完;
join(long millis):等待被join線程執(zhí)行最長為mills豪秒,在這之后即使被join線程沒有執(zhí)行完也不再等待;
join(long millis, int nanos):等待被join線程執(zhí)行最長時(shí)間為millis毫秒+nanos微秒。(此方法基本用不上)。
2:后臺(tái)線程:
有一種線程,他是在后臺(tái)運(yùn)行,他的任務(wù)是為其他線程服務(wù),這種線程被稱為“后臺(tái)線程”、“守護(hù)線程”或“精靈線程”。當(dāng)所有前臺(tái)線程都死亡后,后臺(tái)線程會(huì)自動(dòng)死亡。
示例代碼:
package org.frzh.thread;
public class DaemonThread extends Thread{
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(getName() + " " +i);
}
}
public static void main(String[] args) {
DaemonThread dt = new DaemonThread();
//將此線程設(shè)置為后臺(tái)線程
dt.setDaemon(true);
dt.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
//前臺(tái)線程結(jié)束,那么后臺(tái)線程dt也會(huì)結(jié)束,所以它執(zhí)行不到999
}
}
主線程默認(rèn)是前臺(tái)線程,前臺(tái)線程創(chuàng)建的子線程默認(rèn)是前臺(tái)線程,后臺(tái)線程創(chuàng)建的子線程默認(rèn)是后臺(tái)線程。
3.線程睡眠(sleep):
前面的join方法是讓調(diào)用線程等待被join線程執(zhí)行完之后再繼續(xù)執(zhí)行,而sleep()方法是讓調(diào)用線程阻塞一段時(shí)間后再重新進(jìn)入就緒狀態(tài)等待被調(diào)度。因此它通常用來暫停程序的執(zhí)行。
示例代碼:
package org.frzh.thread;
import java.util.Date;
public class SleepThread{
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println("當(dāng)前時(shí)間:" + new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
sleep()方法的兩種重載方式:
static void sleep(long millis):讓當(dāng)前線程暫停millis毫秒,并進(jìn)入阻塞狀態(tài)。該方法會(huì)受到系統(tǒng)計(jì)時(shí)器和線程調(diào)度器的精度和準(zhǔn)度的影響。
static void sleep(long millis, int nanos):暫停mills毫秒+nanos微秒,并進(jìn)入阻塞狀態(tài),同樣會(huì)受系統(tǒng)計(jì)時(shí)器和線程調(diào)度器的精度和準(zhǔn)度的影響?;静挥谩?/p>
4.線程讓步(yield):
yield()方法和sleep方法有點(diǎn)類似,它同樣可以使當(dāng)前正在運(yùn)行的線程暫停,但他不會(huì)阻塞該線程,只是將他轉(zhuǎn)入就緒狀態(tài)(注意不是阻塞狀態(tài))。yield()方法只會(huì)讓和它同等優(yōu)先級(jí)或更高優(yōu)先級(jí)的線程有被執(zhí)行的機(jī)會(huì),所以某一線程調(diào)用該方法后可能又被重新調(diào)度回來繼續(xù)執(zhí)行。
示例代碼:
package org.frzh.thread;
public class YieldThread extends Thread{
public YieldThread() {
}
public YieldThread(String name) {
super(name);
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + " " +i);
if (i == 20) {
//當(dāng)前線程讓步
Thread.yield();
}
}
}
public static void main(String[] args) {
//啟動(dòng)兩條并發(fā)線程
YieldThread yt1 = new YieldThread("高級(jí)");
//設(shè)置yt1為最高優(yōu)先級(jí)
yt1.setPriority(Thread.MAX_PRIORITY);
yt1.start();
YieldThread yt2 = new YieldThread("低級(jí)");
yt2.setPriority(Thread.MIN_PRIORITY);
yt2.start();
/*
* 如果不給線程設(shè)置優(yōu)先級(jí),則兩個(gè)線程的優(yōu)先級(jí)是相同的,所以兩線程會(huì)交替執(zhí)行,當(dāng)調(diào)用yield后會(huì)讓另一個(gè)線程執(zhí)行;
* 但是,給兩個(gè)線程分別設(shè)置上述優(yōu)先級(jí)之后,剛開始高級(jí)線程執(zhí)行,當(dāng)i=20時(shí),調(diào)用yield,但由于yield方法只會(huì)
* 給和它同優(yōu)先級(jí)或更高優(yōu)先級(jí)的線程執(zhí)行機(jī)會(huì),所以此時(shí)仍是高級(jí)線程執(zhí)行,而不會(huì)讓給低級(jí)線程
*/
}
}
5:改變線程的優(yōu)先級(jí):
此舉比較簡(jiǎn)單,只需調(diào)用調(diào)用實(shí)例方法setPriority(int priority)方法即可。每個(gè)線程默認(rèn)與其父線程的優(yōu)先級(jí)相同,main線程默認(rèn)具有普通優(yōu)先級(jí)(5)。java提供1~10個(gè)優(yōu)先級(jí),也可以使用三個(gè)靜態(tài)常量:
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
注意的是:盡管java提供10個(gè)優(yōu)先級(jí),但是不同的系統(tǒng)支持的優(yōu)先級(jí)不一樣,所以盡量避免直接使用1~10之間的數(shù)字,而使用靜態(tài)常量,以保證具有良好的可移植性。
- Java使用Condition控制線程通信的方法實(shí)例詳解
- Java使用阻塞隊(duì)列控制線程通信的方法實(shí)例詳解
- Java編程中實(shí)現(xiàn)Condition控制線程通信
- java線程池:獲取運(yùn)行線程數(shù)并控制線程啟動(dòng)速度的方法
- Java線程的生命周期和狀態(tài)控制_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- 舉例講解Java中Piped管道輸入輸出流的線程通信控制
- Java中使用阻塞隊(duì)列控制線程集實(shí)例
- java控制線程運(yùn)行
- java信號(hào)量控制線程打印順序的示例分享
- Java join 線程控制用法
- Java 控制線程的方法
相關(guān)文章
詳解使用spring aop實(shí)現(xiàn)業(yè)務(wù)層mysql 讀寫分離
本篇文章主要介紹了使用spring aop實(shí)現(xiàn)業(yè)務(wù)層mysql 讀寫分離,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01一文帶你快速學(xué)會(huì)JDBC及獲取連接的五種方式
JDBC(Java Database Connectivity)是一個(gè)獨(dú)立于特定數(shù)據(jù)庫管理系統(tǒng)、通用的SQL數(shù)據(jù)庫存取和操作的公共接口,下面這篇文章主要給大家介紹了關(guān)于如何通過一文帶你快速學(xué)會(huì)JDBC及獲取連接的五種方式,需要的朋友可以參考下2022-09-09Java版仿QQ驗(yàn)證碼風(fēng)格圖片驗(yàn)證碼
這篇文章主要為大家分享了java圖片驗(yàn)證碼實(shí)例代碼,感興趣的小伙伴們可以參考一下2016-04-04SpringBoot 中大文件(分片上傳)斷點(diǎn)續(xù)傳與極速秒傳功能的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot 中大文件(分片上傳)斷點(diǎn)續(xù)傳與極速秒傳功能的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07java 運(yùn)行報(bào)錯(cuò)has been compiled by a more recent version of the J
java 運(yùn)行報(bào)錯(cuò)has been compiled by a more recent version of the Java Runtime (class file version 54.0)2021-04-04Java阻塞隊(duì)列的實(shí)現(xiàn)及應(yīng)用
這篇文章主要介紹了剖析Java中阻塞隊(duì)列的實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景,這里也對(duì)阻塞和非阻塞隊(duì)列的不同之處進(jìn)行了對(duì)比,需要的朋友可以參考下2021-10-10