Java多線程——<八>多線程其餘概念

1、概述html

  到第八節,就把多線程基本的概念都說完了。把前面的全部文章加鏈接在此:java

  Java多線程——<一>概述、定義任務windows

  Java多線程——<二>將任務交給線程,線程聲明及啓動多線程

  Java多線程——<三>簡單的線程執行:Executoride

  Java多線程——<四>讓線程有返回值優化

  Java多線程——<五>後臺線程(daemon)this

  Java多線程——<六>更方便的線程spa

  Java多線程——<七>多線程的異常捕捉操作系統

  均是我的理解和總結,代碼均來自《thinking in java》,有問題歡迎你們指正。線程

2、多線程的其餘概念

  1.休眠

  休眠,其實就是讓線程暫停一段時間,也就是阻塞一段時間。例如:每一個打印以後,每一個線程都要睡眠(即阻塞),這使得線程調度器能夠切換到另外一個線程,進而驅動另外一個任務。這致使了線程在執行順序上獲得了保證,能夠經過查看打印輸出消息證明這一點。

public class TaskSleepingTask extends Task{
    @Override
    public void run() {
        try{
            while(countDown-- > 0){
                System.out.println(status());
                /*
                 * 每一個打印以後,每一個線程都要睡眠(即阻塞),這使得線程調度器能夠切換到另外一個線程,進而驅動另外一個任務
                 */
                TimeUnit.MICROSECONDS.sleep(100000);
            }    
        /*
         * 由於異常不能跨線程傳回給main,因此你必須在線程裏處理該異常
         */
        }catch(InterruptedException e){
            System.out.println();
        }
    }
    public static void main(String[] args){
        ExecutorService exec = Executors.newCachedThreadPool();
        for(int i = 0 ; i < 5 ; i++){
            exec.execute(new TaskSleepingTask());
        }
        exec.shutdown();
    }
}

  可是,這不表明你就能夠經過休眠的方式來保證任務的執行順序(順序行爲依賴於底層的線程機制,這種機制在不一樣的操做系統之間是有差別的

  要想控制順序的解決辦法:一、同步控制,二、協做線程(之後再作序數)

  2.優先級

  優先級表明了該線程的重要性,線程調度器將傾向於讓優先級高的線程先執行(但這不意味着優先權較低的線程將得不到執行,即優先權不會致使死鎖)。優先級較低的線程僅僅是執行頻率較低,在絕大多數時間裏,全部線程都應該以默認優先級運行,試圖操縱線程優先級一般是一種錯誤。

  經過Thread.currentThread()方法來得到對驅動該任務的Thread對象的引用,而後設置線程優先級。

public class TaskPriority implements Runnable{
    private int countDown = 5;
    /*
     * 變量d用來確保不進行任何編譯器優化
     */
    @SuppressWarnings("unused")
    private volatile double d;//no optimization
    private int priority;
    public TaskPriority(int priority){
        this.priority = priority;
    }
    /*
     * 打印線程的名稱、線程的優先級以及線程所屬的「線程組」
     *在線程內部,經過調用Thread.currentThread()來得到對驅動該任務的Thread對象的引用
     */
    public String toString(){
        return Thread.currentThread()+":"+countDown;
    }
    @Override
    public void run() {
        /*
         * 優先級應該在run的開頭部分設定,在構造器中設置他們不會有任何好處,由於Executor在此刻尚未開始執行任務
         */
        Thread.currentThread().setPriority(priority);
        /*
         * 執行了10000次浮點運算,數學 運算是能夠中斷的,這裏運算時間足夠長,
         * 所以線程調度機制纔來得及介入,交換任務並關注優先級,使得最高優先級的線程被優先選擇
         */
        while(true){
            for(int i = 1 ;i < 10000;i++){
                d+=(Math.PI + Math.E)/(double)i;
                if(i%1000==0)
                    Thread.yield();
                System.out.println(this);
                if(--countDown == 0 ) 
                    return;
            }
        }
    }
    public static void main(String[] args){
        ExecutorService exec = Executors.newCachedThreadPool();
        for(int i = 0 ; i < 5;i++){
            exec.execute(new TaskPriority(Thread.MIN_PRIORITY));//1
        }
        exec.execute(new TaskPriority(Thread.MAX_PRIORITY));//10
        exec.shutdown();
    }
}

  儘管jdk有10個優先級,可是它與多數操做系統都不能映射得很好(windows7個,solaris2個),惟一可移植的方法是當調整優先級的時候,只試用MAX_PRIORITY/NORM_PRIORITY/MIN_PRIORITY三種聲明

  3.讓步

  在你已經確認完成了在run方法的循環的一次迭代過程當中所需的工做,就能夠給線程調度機制一個暗示:你的工做已經作的差很少了,可讓別的線程試用cpu了。(讓相同優先級的其餘線程能夠運行)。

  java提供了調用yield()方法來實現。過這只是暗示沒有任何機制保證它會被採納,因此不能依賴該方法。如上例。

相關文章
相關標籤/搜索