Java Thread Programming 1.6 – Thread Prioritization

來源:互聯網
上載者:User
  System Thread Priorities—JDK 1.2
Priority Thread Name
5 main
8 Finalizer
10 Reference Handler
5 Signal dispatcher
5 AWT-Windows
6 AWT-EventQueue-0
5 SunToolkit.PostEventQueue-0
4 Screen Updater
 A notable change in JDK 1.2 is that the priority of the Finalizer thread was increased from 1 to 8 to help ensure that the garbage collector gets more of a chance to run and free up memory. Jdk1.2中Finalizer線程的優先順序從1升高到8,確保垃圾收集器能及時回收資源釋放記憶體 When assigning priorities to your threads, you should consider the relative priorities of the system threads to be sure your threads don’t overwhelm their operations. By default, when a new Thread is constructed, it runs at the same priority as the thread that constructed it. Most new threads are constructed directly or indirectly by the main thread and will therefore run at a priority of 5. This works well under many scenarios, but there are times when you will want to raise or lower a thread’s priority. 子線程的優先順序和父線程的優先順序相同,大部分線程從main線程建立,所以優先順序為5 There are three public static final int member variables of Thread that indicate the range of priority values that can be passed to setPriority(). Thread.MAX_PRIORITY Thread.MIN_PRIORITY Thread.NORM_PRIORITY  Thread類中有三個靜態優先順序變數Thread.MAX_PRIORITY,最高優先順序,通常為10Thread.MIN_PRIORITY,最低優先順序,通常為1Thread.NORM_PRIORITY,一般優先順序,通常為5   getPriority()  The getPriority() method of Thread returns an int representing the current priority of the thread. Generally, a thread’s priority does not change over its lifetime, but it can.  getPriority()返回線程的當前優先順序,通常線程的優先順序在其生命週期中不會變,但可以變  setPriority()  The setPriority() method of Thread takes an int as a parameter indicating the new priority for the thread. The setPriority() method can be invoked either before the thread is started or once it is running. Some VMs might allow you to change the priority of the system threads, but this is not recommended—even if it is permitted. setPriority()設定線程新的優先順序,可以線上程開始前調用,也可以線上程運行中調用,有些虛擬機器允許改變系統線程的優先順序,但我們不推薦這麼做 Calls to setPriority can throw a SecurityException if the calling thread is not permitted to make the priority change. This will happen only if there is a SecurityManager installed and it rejects the change request. By default, applications do not have a SecurityManager. 如果不允許線程優先順序改變,調用setPriority()方法時會拋出SecurityException異常,當安裝了SecurityManager時,可能會出現這種情況 An IllegalArgumentException will be thrown if the specified priority is greater than Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY.allowed for the thread group. For example, in this code fragment Thread t = //...ThreadGroup tg = t.getThreadGroup();int groupMax = tg.getMaxPriority(); the maximum value for the thread priority of thread t is groupMax. Usually, this is the same as Thread.MAX_PRIORITY. When groupMax is less than Thread.MAX_PRIORITY, calls to setPriority() still work, but will silently reduce the value passed to groupMax. If groupMax is 6 and setPriority(9) is called, the code will run as if setPriority(6) was called instead. See Chapter 10, “Thread Groups,” for more on ThreadGroup. 如果將線程優先順序設定線上程組的Thread.MAX_PRIORITY,和Thread.MIN_PRIORITY之外,會拋出IllegalArgumentException異常。線程組允許的最大優先順序和Thread.MAXPRIORITY可能會不一致,如果線程組最大優先順序為6,而將線程優先順序設定為9,那麼代碼執行的結果和setPriority(6)一樣。     Thread States  
State Blocked Interrupted Discription
Running     Current running on the processor
Ready to run     Waiting for the processor
Sleeping Will move to “ready to run” stateafter a certain amount of time has eclipsed or after being interrupted
Waiting Will move to “ready to run” stateafter being notice, after timeout or after being interrupted
Blocked on I/O   Will move to “ready to run” after I/OCondition changes(for example,a byte of date is read)
Blocked on sync   Will move to “ready to run” when lock is acquired(passes synchronized statement)
 Threads can be blocked in one of four states. When a thread executes Thread.sleep(), it blocks until the specified number of milliseconds passes or until it is interrupted by another thread. When a thread encounters a wait() statement (see Chapter 8, “Inter-thread Communication,” for more on the wait/notify mechanism), it blocks until it is notified, interrupted, or the specified number of milliseconds elapses (if a timeout was specified). There are many ways a thread can block waiting on different I/O methods. One common way is the read() method of InputStream. This method blocks until a byte of data is read from the stream. It can block indefinitely, and no timeout can be specified. A thread can also block waiting to acquire exclusive access to an object’s lock. The synchronized statement and synchronized method modifier (see Chapter 7, “Concurrent Access to Objects and Variables,” for more on synchronization) are used to control concurrent access by more than one thread to a section of code. A thread will block on synchronized until it gets the specified lock. It can block indefinitely, and no timeout can be specified. 有四種方式線程會被阻塞:1、調用Thread.sleep(),時間完成、被其他線程打斷時改變狀態2、wait/notify時線程遇到wait()時,當被notified,被別的線程打斷,或者特定時間結束時改變狀態3、I/O阻塞4、鎖阻塞,同步鎖時,線程得到此鎖時改變狀態 Notice that not all blocked states are interruptible. When a thread is blocked waiting to read a byte of data from an InputStream, it will not respond to interrupts (see Chapter 15, “Breaking Out of a Blocked I/O State,” for some techniques for dealing with this). When a thread is blocked waiting to get the lock required by a synchronized statement, it also will not respond to interrupt requests (see Chapter 17, “BooleanLock Utility,” for a technique that deals with long waits for locks). 不是所有的阻塞狀態都可以被打斷的,I/O阻塞和鎖阻塞是不能被中斷的  Thread.yield()  To help ensure that other threads in the VM get a turn to run on the processor, a thread can voluntarily give up its turn early. If a thread invokes the static method Thread.yield(), the thread scheduler will swap it off the processor and allow another thread to run. It is likely (but not guaranteed) that only threads having a priority equal to or greater than the one that yielded control will be considered by the thread scheduler. Thread.yield():線程自願讓出cpu控制權 A thread implicitly yields the processor when it goes to sleep or otherwise blocks. The Thread.yield() method allows a thread to specify other times that are convenient for it to pause to allow other threads access to the processor. If you have a thread that frequently blocks on its own, there is no need to make Thread.yield() calls. But, if you have a thread that is performing a long non-blocking calculation, an occasional call to Thread.yield() can help split up the processor resources among the other threads. Be careful not to overuse Thread.yield() as some system overhead is incurred to perform a context switch between threads. As a rough guideline, try to avoid calling Thread.yield() more than five times per second. 當線程阻塞時(四種原因),線程隱式自行yield。如果線程本身經常阻塞,就沒有必要顯式調用yield,如果線程執行一個長時間不阻塞的大運算,調用一下能夠給其他進程平分一下處理器資源。注意:不要頻繁調用,因為yield時系統做環境切換,很是耗費系統資源和時間,避免疫秒內調用五次以上的yield。 執行個體: PriorityYield.java/* * Created on 2005-7-8 * * Java Thread Programming - Paul Hyde  * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 *  */package org.tju.msnrl.jonathan.thread.chapter1; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo *      blog.yesky.net/jonathanundersun *  * Enjoy Life with Sun! *  */public class PriorityYield {    private volatile int counter;    private Thread innerThread;    private volatile boolean stopRequest;    private boolean yield;        public PriorityYield(String name,int priority,boolean yield){        this.yield = yield;        this.counter = 0;        this.stopRequest = false;                Runnable r = new Runnable(){            public void run(){                try{                    runwork();                }catch(Exception e){                    System.out.println(e.getMessage());                }            }        };                innerThread = new Thread(r,name);        innerThread.setPriority(priority);    }        /** 線程主體 */    public void runwork(){        Thread.yield();        while(!this.stopRequest){            if(this.yield){                Thread.yield();            }            counter++;                        double x = 0;            for(int i = 0; i < 1000; i++)//讓線程處於活動狀態,而不是sleep                x = Math.PI*i/Math.E;        }    }     /** 開始線程 */    public void startThread(){        this.innerThread.start();    }        /** 結束線程 */    public void stopThread(){        this.stopRequest = true;    }        public int getCounter(){        return this.counter;    }        /** 返回線程優先順序和線程名 */    public String getPriorityandName(){        return "Thread:" + innerThread.getName() + "/Priority:" + innerThread.getPriority();    }        public static void runMain(boolean yield){        /*定義三個線程*/        PriorityYield[] pys = new PriorityYield[3];        pys[0] = new PriorityYield("PY0",3,yield);        pys[1] = new PriorityYield("PY1",6,yield);        pys[2] = new PriorityYield("PY2",6,yield);                try{            Thread.sleep(1000);        }catch(InterruptedException e){}                /*啟動三線程*/        for(int i = 0 ; i < pys.length; i++){            pys[i].startThread();        }                long startTime = System.currentTimeMillis();                /*讓線程運行一段時間*/        try{            Thread.sleep(10000);        }catch(InterruptedException e){}                /*停止線程運行*/        for(int i = 0; i < pys.length; i++){            pys[i].stopThread();        }                long stopTime = System.currentTimeMillis();                /*等線程完全停止運行*/        try{            Thread.sleep(1000);        }catch(InterruptedException e){}                /*獲得三線程總計數*/        int totalCounter = 0;        for(int i = 0; i < pys.length; i++){            totalCounter += pys[i].getCounter();        }                /*輸出統計結果*/        System.out.println("totalcount=" + totalCounter + "  counter/ms=" + totalCounter/(stopTime - startTime));        for(int i = 0; i < pys.length; i++){            System.out.println(pys[i].getPriorityandName() + ", count=" + pys[i].counter + " ," + pys[i].counter*100/totalCounter + "%");        }    }        public static void main(String[] args) {        Runnable r =new Runnable(){            public void run(){                System.out.println("run without yield");                runMain(false);//不使用yield                System.out.println();                System.out.println("run with yield");                runMain(true);//使用yield            }        };        Thread t = new Thread(r,"PriorityYield");        t.setPriority(Thread.MAX_PRIORITY - 1);        t.start();    }}  輸出結果: run without yieldtotalcount=454665  counter/ms=45Thread:PY0/Priority:3, count=0 ,0%Thread:PY1/Priority:6, count=235049 ,51%Thread:PY2/Priority:6, count=219616 ,48% run with yieldtotalcount=401611  counter/ms=40Thread:PY0/Priority:3, count=0 ,0%Thread:PY1/Priority:6, count=200805 ,49%Thread:PY2/Priority:6, count=200806 ,50% 通過調用yield的對比實驗很明顯看出1、  優先順序高的獲得更多的處理器周期2、  同一優先順序的線程又相同的運行機會3、  調用yield不會增加效能,而是降低了cpu總周期 Also note that without yielding, the count/ms was about 76 (line 3), and when yielding was done, it was cut down to about 25 (line 10). This shows that the yielding caused a lot of context switches that brought with them some significant overhead. In this example, the excessive yielding wasted processor resources. 頻繁的yield浪費處理器資源  When assigning priorities to the threads in your application, use the higher priorities only for threads that block frequently (sleeping, waiting, I/O). CPU-intensive calculations should be done with a medium- to low-priority thread to ensure that the processor is not hogged. Avoid setting a priority to Thread.MAX_PRIORITY unless the thread spends nearly all of its time blocked or is very short-lived. 給經常阻塞的線程高的優先順序,給密集運算的線程中低優先順序保證處理器不會被獨佔,避免設定優先權為Thread.MAX_PRIORITY,除非線程的生命週期特別短或者整個生命週期中基本都處於阻塞狀態 Thread scheduling varies from VM to VM and from operating system to operating system. Because of these differences, prioritization should only be used to try to improve responsiveness and efficiency, and should not be relied upon for program correctness. 不同的虛擬機器不同的作業系統有不同的線程調用機制,由於這些不同,線程優先順序只是用來提高響應和效率的一種手段,不能作為程式正確性的依賴。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.