04 Java線程學習2

線程狀態

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-4tNQKFhI-1593158875388)(C:\Users\Tangs\AppData\Roaming\Typora\typora-user-images\1593090312049.png)]

線程方法

方法 說明
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+"天");
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章