1、線程睡眠—sleep:
線程睡眠的原因:線程執行的太快,或需要強制執行到下一個線程。
線程睡眠的方法(兩個):
sleep(long millis)在指定的毫秒數內讓正在執行的線程休眠。
sleep(long millis,int nanos)在指定的毫秒數加指定的納秒數內讓正在執行的線程休眠。
線程睡眠的代碼演示:
public class SynTest {
public static void main(String[] args) {
new Thread(new CountDown(),"倒計時").start();
}
}
class CountDown implements Runnable{
int time = 10;
public void run() {
while (true) {
if(time>=0){
System.out.println(Thread.currentThread().getName() + ":" + time--);
try {
Thread.sleep(1000); //睡眠時間爲1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
每隔一秒則會打印一次,打印結果爲:
倒計時:10
倒計時:9
倒計時:8
倒計時:7
倒計時:6
倒計時:5
倒計時:4
倒計時:3
倒計時:2
倒計時:1
倒計時:0
擴展:Java線程調度是Java多線程的核心,只有良好的調度,才能充分發揮系統的性能,提高程序的執行效率。但是不管程序員怎麼編寫調度,只能最大限度的影響線程執行的次序,而不能做到精準控制。因爲使用sleep方法之後,線程是進入阻塞狀態的,只有當睡眠的時間結束,纔會重新進入到就緒狀態,而就緒狀態進入到運行狀態,是由系統控制的,我們不可能精準的去幹涉它,所以如果調用Thread.sleep(1000)使得線程睡眠1秒,可能結果會大於1秒。
2、線程讓步—yield:
該方法和sleep方法類似,也是Thread類提供的一個靜態方法,可以讓正在執行的線程暫停,但是不會進入阻塞狀態,而是直接進入就緒狀態。相當於只是將當前線程暫停一下,然後重新進入就緒的線程池中,讓線程調度器重新調度一次。也會出現某個線程調用yield方法後暫停,但之後調度器又將其調度出來重新進入到運行狀態。
public class SynTest {
public static void main(String[] args) {
yieldDemo ms = new yieldDemo();
Thread t1 = new Thread(ms,"張三吃完還剩");
Thread t2 = new Thread(ms,"李四吃完還剩");
Thread t3 = new Thread(ms,"王五吃完還剩");
t1.start();
t2.start();
t3.start();
}
}
class yieldDemo implements Runnable{
int count = 20;
public void run() {
while (true) {
if(count>0){
System.out.println(Thread.currentThread().getName() + count-- + "個瓜");
if(count % 2 == 0){
Thread.yield(); //線程讓步
}
}
}
}
}
sleep和yield的區別:
①、sleep方法聲明拋出InterruptedException,調用該方法需要捕獲該異常。yield沒有聲明異常,也無需捕獲。
②、sleep方法暫停當前線程後,會進入阻塞狀態,只有當睡眠時間到了,纔會轉入就緒狀態。而yield方法調用後 ,是直接進入就緒狀態。
3、線程合併—join:
當B線程執行到了A線程的.join()方法時,B線程就會等待,等A線程都執行完畢,B線程纔會執行。
join可以用來臨時加入線程執行。以下爲代碼演示:
public static void main(String[] args) throws InterruptedException {
yieldDemo ms = new yieldDemo();
Thread t1 = new Thread(ms,"張三吃完還剩");
Thread t2 = new Thread(ms,"李四吃完還剩");
Thread t3 = new Thread(ms,"王五吃完還剩");
t1.start();
t1.join();
t2.start();
t3.start();
System.out.println( "主線程");
}
4、停止線程:
原stop方法因有缺陷已經停用了,那麼現在改如何停止線程?現在分享一種,就是讓run方法結束。
開啓多線程運行,運行的代碼通常是循環結構,只要控制住循環,就可以讓run方法結束,也就是線程結束。
具體代碼如下:
1 public class StopThread {
2
3 public static void main(String[] args) {
4 int num = 0;
5 StopTh st = new StopTh();
6 Thread t1 = new Thread(st);
7 Thread t2 = new Thread(st);
8 t1.start();
9 t2.start();
10 //設置主線程執行50次,執行結束之後停止線程
11 while (true) {
12 if(num++ == 50){
13 st.flagChange();
14 break;
15 }
16 System.out.println(Thread.currentThread().getName() + "..." + num);
17 }
18 }
19 }
20
21 class StopTh implements Runnable{
22
23 private boolean flag = true;
24 public void run() {
25 while(flag){
26 System.out.println(Thread.currentThread().getName() + "stop run" );
27 }
28 }
29 public void flagChange(){
30 flag = false;
31 }
32 }
特殊情況:當線程處於了凍結狀態,就不會讀取到標記,也就不會結束。當沒有指定方法讓凍結的線程回覆到運行狀態時,我們需要對凍結狀態進行清除,也就是強制讓線程恢復到運行狀態中來,這樣可就可以操作標記讓線程結束。
Thread類提供該方法: interrupt();(如果線程在調用Object類的wait()、wait(long)、wait(long,int)方法,或者該類的join()、join(long)、join(long、int)、sleep(long)或sleep(long、int)方法過程中受阻,則其中斷狀態將被清除,還將收到一個InterruptedException。)
5、設置優先級:
每個線程執行時都有一個優先級的屬性,優先級高的線程可以獲得較多的執行機會,而優先級低的線程則獲得較少的執行機會。與線程休眠類似,線程的優先級仍然無法保障線程的執行次序。只不過,優先級高的線程獲取CPU資源的概率較大,優先級低的也並非沒機會執行。
Thread類中提供了優先級的三個常量,代碼如下:
MAX_PRIORITY =10
MIN_PRIORITY =1
NORM_PRIORITY =5
-----------------------------------------------------
ThreadDemo td = new ThreadDemo();
Thread t1 = new Thread(td,"張三");
t1.priority(9); //設置優先級
t1.start(); //設置完畢