線程狀態
線程方法
方法 | 說明 |
---|---|
setPriority(int newPriority) | 更改線程的優先級 |
static void sleep(long millis) | 在指定的毫秒數內讓當前正在執行的線程休眠 |
void join() | 等待該線程終止 |
static void yield() | 暫停當先正在執行的線程對象,並執行其他線程 |
void interrupt() | 中斷線程,不要使用這個方法 |
bollean isAlive() | 測試線程是否處於活動狀 |
停止線程
- 不推薦使用JDK提供的stop()、destroy()方法。【已棄用】
- 推薦使用自己的停止方法。
- 建議使用一個標誌位進行終止變量,當flag=false,則終止線程運行
public class TestStop implements Runnable{
//1.線程中定義線程體使用的標誌
private boolean flag = true;
@Override
public void run(){
//2.線程體使用該標誌
while(flag){
System.out.println("run...Thread");
}
}
//3.對外提供方法改變標識
public void stop(){
this.flag = false;
}
//測試
public static void main(String[] args){
TestStop testStop = new TestStop();
new Thread(testStop).start();
for(int i = 0; i < 100; i++){
if(i == 50){
//調用stop方法切換標誌位,使線程停止
testStop.stop();
System.out.println("該線程停止...")
}
}
}
}
線程休眠
- sleep(時間)指定當前線程阻塞的毫秒數
- sleep存在異常InterruptedException
- sleep時間達到後,線程進入就緒狀態
- sleep可以模擬網絡延時,倒計時等
- 每一個對象都有一個鎖,sleep不會釋放鎖
網絡延遲:
public class TestSleep implements Runnable{
private int ticketNums = 10;
@Override
public void run(){
while(true){
if(ticketNums <= 0){
break;
}
//模擬延遲
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"--->拿到了第"+ticketNums+"張票")
}
}
public static void main(String[] args){
TestSleep testSleep = new TestSleep();
new Thread(testSleep, "黃牛").start;
new Thread(testSleep, "小米").start;
new Thread(testSleep, "小偷").start;
}
}
模擬倒計時
public class TestTimeDown{
public static void main(String[] args){
Date startTime = new Date(System.currentTimeMillis()); //獲取系統當前時間
while(true){
try{
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime = new Date(System.currentTimeMillis()); //更新當前時間
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//模擬倒計時
public static void tenDown() throws InterruptedException{
int num = 10;
while(true){
Thread.sleep(1000); //單位:毫秒
System.out.println(num--);
if(num <= 0){
break;
}
}
}
}
線程禮讓
- 禮讓線程,讓當前正在執行的線程暫停,但不阻塞
- 將線程從運行狀態轉爲就緒狀態
- 讓CPU重新調度,禮讓不一定成功,看CPU心情
public class TestYield{
public static void main(String[] args){
MyYield myYield = new MyYield();
new Thread(myYield, "a").start();
new Thread(myYield, "b").start();
}
}
class MyYield implements Runnable{
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+"線程開始執行");
Thread.yield(); //禮讓
System.out.println(Thread.currentThread().getName()+"線程結束執行");
}
}
Join 禮讓
- Join合併線程,待此線程執行完成後,再執行其他線程,其他線程阻塞
- 可以理解爲插隊
public class JoinTest implements Runnable{
@Override
public void run(){
for(int i = 0; i < 100; i++){
System.out.println("VIP線程"+i+"來額");
}
}
public static void main(String[] args){
//啓線程
JoinTest joinTest = new JoinTest();
Thread thread = new Thread(joinTest);
thread.start();
//主線程
for(int i = 0; i < 200; i++){
if(i == 30){
thread.join();
}
}
}
}
線程狀態觀測
-
Thread.State
線程狀態,線程可以處於以下狀態之一。
-
NEW
尚未啓動的線程處於此狀態
-
RUNNABLE
在Java虛擬機中執行的線程處於此狀態
-
BLOCKED
被阻塞等待監視器鎖定的線程處於此狀態
-
WAITING
正在等待另一個線程執行特定動作的線程處於此狀態
-
TIMED_WAITING
正在等待另一個線程執行動作達到指定等待時間的線程處於此狀態
-
TERMINATED
已退出的線程處於此狀態
-
一個線程客戶以在給定時間點處於一個狀態。這些狀態是不反映任何操作系統線程狀態的虛擬機狀態。
線程優先級
-
Java提供一個線程調度器來監控程序中啓動後進入就緒狀態的所有線程,線程調度器按照優先級決定應該調度哪個線程來執行。
-
線程的優先級用數字表示,範圍從1~10
- Thread.MIN_PRIORITY = 1;
- Thread.MAX_PRIORITY = 10;
- Thread.NORM_PRIORITY = 5;
-
使用以下方式改變或獲取優先級
- getPriority().setPriority(int xxx)
優先級低只是意味着獲得調度的概率低,並不是優先級低就不會被調用了,這就是看CPU的調度,當優先級低的先執行就會是“性能倒置”
優先級的設定建議在start()調度前(先設置優先級在start跑)
守護線程(daemon)
- 線程分爲用戶線程和守護線程
- 虛擬機必須確保用戶線程執行完畢
- 虛擬機不用等待守護線程執行完畢
- such as,後臺記錄操作日誌,監控內存,垃圾回收(gc)等待…
注意:守護線程不能持有任何需要關閉的資源,例如打開文件等,因爲虛擬機退出時,守護線程沒有任何機會來關閉文件,這會導致數據丟失。
public class DaemonTest{
public static void main(String[] args){
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true); //默認是false表示是用戶線程,正常的線程都是用戶線程
}
}
class God implements Runnable{
@Override
public void run(){
while(true){
System.out.println("上帝保佑你");
}
}
}
class You implements Runnable{
@Override
public void run(){
for(int i = 0; i < 36500; i++){
System.out.println("你開心的活了"+i+"天");
}
}
}