多線程基礎介紹第二篇之睡眠、讓步、合併、停止、設置優先級

1、線程睡眠---sleep:

    線程睡眠的原因:線程執行的太快,或需要強制執行到下一個線程。

    線程睡眠的方法(兩個):sleep(long millis)在指定的毫秒數內讓正在執行的線程休眠。

                sleep(long millis,int nanos)在指定的毫秒數加指定的納秒數內讓正在執行的線程休眠。

擴展:Java線程調度是Java多線程的核心,只有良好的調度,才能充分發揮系統的性能,提高程序的執行效率。但是不管程序員怎麼編寫調度,只能最大限度的影響線程執行的次序,而不能做到精準控制。因爲使用sleep方法之後,線程是進入阻塞狀態的,只有當睡眠的時間結束,纔會重新進入到就緒狀態,而就緒狀態進入到運行狀態,是由系統控制的,我們不可能精準的去幹涉它,所以如果調用Thread.sleep(1000)使得線程睡眠1秒,可能結果會大於1秒。

整理:睡眠,就是讓線程進入阻塞狀態,時間到了,進入就緒狀態,但由於無法控制就緒--->運行狀態的時間,所以時間實際可能會大於睡眠時間。並且會拋出異常

//異常連接

2、線程讓步---yield:

     該方法和sleep方法類似,也是Thread類提供的一個靜態方法,可以讓正在執行的線程暫停,但是不會進入阻塞狀態,而是直接進入就緒狀態。相當於只是將當前線程暫停一下,然後重新進入就緒的線程池中,讓線程調度器重新調度一次。也會出現某個線程調用yield方法後暫停,但之後調度器又將其調度出來重新進入到運行狀態。

整理:讓步,就是讓線程從運行---->就緒狀態,讓線程重新調用下

sleep和yield的區別:

    ①、sleep方法聲明拋出InterruptedException,調用該方法需要捕獲該異常。yield沒有聲明異常,也無需捕獲。

    ②、sleep方法暫停當前線程後,會進入阻塞狀態,只有當睡眠時間到了,纔會轉入就緒狀態。而yield方法調用後 ,是直接進入就緒狀態。

  3、線程合併---join:

    當B線程執行到了A線程的.join()方法時,B線程就會等待,等A線程都執行完畢,B線程纔會執行。

    join可以用來臨時加入線程執行。

整理:線程合併,就是讓A線程把任務執行完,B線程才能開始執行

 4、停止線程:

    原stop方法因有缺陷已經停用了,那麼現在改如何停止線程?現在分享一種,就是讓run方法結束。

    開啓多線程運行,運行的代碼通常是循環結構,

整理:利用run方法,設置條件,結束線程。但是有一種特殊情況:

線程處於凍結狀態,標記就無法讀取到。

 特殊情況:當線程處於了凍結狀態,就不會讀取到標記,也就不會結束。當沒有指定方法讓凍結的線程回覆到運行狀態時,我們需要對凍結狀態進行清除,也就是強制讓線程恢復到運行狀態中來,這樣可就可以操作標記讓線程結束。

      Thread類提供該方法: interrupt()(鏈接https://mp.csdn.net/postedit/88569774);(如果線程在調用Object類的wait()、wait(long)、wait(long,int)方法,或者該類的join()、join(long)、join(long、int)、sleep(long)或sleep(long、int)方法過程中受阻,則其中斷狀態將被清除,還將收到一個InterruptedException。)

只要控制住循環,就可以讓run方法結束,也就是線程結束。

 5、設置優先級:

    每個線程執行時都有一個優先級的屬性,優先級高的線程可以獲得較多的執行機會,而優先級低的線程則獲得較少的執行機會。與線程休眠類似,線程的優先級仍然無法保障線程的執行次序。只不過,優先級高的線程獲取CPU資源的概率較大,優先級低的也並非沒機會執行。

整理:優先級只能保證獲取CPU資料的概率比優先級低的線程大( setPriority(9))

常用的定義:

 MAX_PRIORITY   =10

 MIN_PRIORITY   =1

 NORM_PRIORITY   =5

package thread.basic;

import jdk.nashorn.internal.objects.annotations.Where;

/**
 * @Package:thread.basic
 * @Class:ThreadState
 * @Description: TODO
 * @Author:何仲奇
 * @Date:Created in 2019-03-14 0:23
 * @Company:
 * @Version:
 * @Modified By:
 */
public class ThreadState {

    public static void main(String[] args) throws InterruptedException {
        //new Thread(new RunnableDemo1(), "倒計時").start();

        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();

        /**
         * 3、線程合併---join:
         *
         *     當B線程執行到了A線程的.join()方法時,B線程就會等待,等A線程都執行完畢,B線程纔會執行。
         *
         *     join可以用來臨時加入線程執行。
         */
       /* t1.start();
        t1.join();

        t2.start();
        t3.start();*/
        System.out.println( "主線程");

        int num = 0;
        StopTh st = new StopTh();
        Thread t11 = new Thread(st);
        Thread t22 = new Thread(st);
        t11.start();
        t22.start();
        //設置主線程執行50次,執行結束之後停止線程
        while (true) {
            if(num++ == 50){
                st.flagChange();
                break;
            }
            System.out.println(Thread.currentThread().getName() + "..." + num);
        }
        //特殊情況:當線程處於了凍結狀態,
        //就不會讀取到標記,也就不會結束。當沒有指定方法讓凍結的線程回覆到運行狀態時,
        // 我們需要對凍結狀態進行清除,也就是強制讓線程恢復到運行狀態中來,這樣可就可以操作標記讓線程結束。
        //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
        RunnableDemo1 td = new RunnableDemo1();
        Thread t111 = new Thread(td,"張三");
        //設置優先級
        t111.setPriority(9);
        t111.start();//設置完畢
    }
}
/**
 * 1、線程睡眠---sleep:
 * <p>
 *     線程睡眠的原因:線程執行的太快,或需要強制執行到下一個線程。
 * <p>
 *     線程睡眠的方法(兩個):sleep(long millis)在指定的毫秒數內讓正在執行的線程休眠。
 * <p>
 *                 sleep(long millis,int nanos)在指定的毫秒數加指定的納秒數內讓正在執行的線程休眠。
 */

/**
 *  擴展:Java線程調度是Java多線程的核心,只有良好的調度,才能充分發揮系統的性能,
 *   提高程序的執行效率。但是不管程序員怎麼編寫調度,只能最大限度的影響線程執行的次序,
 *   而不能做到精準控制。因爲使用sleep方法之後,線程是進入阻塞狀態的,
 *   只有當睡眠的時間結束,纔會重新進入到就緒狀態,而就緒狀態進入到運行狀態,
 *   是由系統控制的,我們不可能精準的去幹涉它,
 *   所以如果調用Thread.sleep(1000)使得線程睡眠1秒,可能結果會大於1秒。
 */

class  RunnableDemo1 implements Runnable {
        int time  = 10;
        @Override
        public void run() {
            while (true) {
                if(time >= 0) {
                    System.out.println(Thread.currentThread().getName() + ":" +time--);
                }
                try {
                    //睡眠時間爲1秒
                    Thread.sleep(1000);
//這裏涉及關於異常問題
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
}
/**
 * 2、線程讓步---yield:
 *該方法和sleep方法類似,也是Thread類提供的一個靜態方法,
 * 可以讓正在執行的線程暫停,但是不會進入阻塞狀態,而是直接進入就緒狀態。
 * 相當於只是將當前線程暫停一下,然後重新進入就緒的線程池中,
 * 讓線程調度器重新調度一次。也會出現某個線程調用yield方法後暫停,
 * 但之後調度器又將其調度出來重新進入到運行狀態。
 */

class YieldDemo implements Runnable{
    int count = 20;
    @Override
    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方法調用後 ,是直接進入就緒狀態。
 */

/**
 * 4、停止線程:
 *
 *     原stop方法因有缺陷已經停用了,那麼現在改如何停止線程?現在分享一種,就是讓run方法結束。
 *
 *     開啓多線程運行,運行的代碼通常是循環結構,只要控制住循環,就可以讓run方法結束,也就是線程結束。
 */
class StopTh implements Runnable{
    private boolean flag = true;
    @Override
    public void run() {
        while(flag){
            System.out.println(Thread.currentThread().getName() + "stop run" );
        }
    }
    public void flagChange(){
        flag = false;
    }
 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章