首頁 >Java >java教程 >Java執行緒優先權

Java執行緒優先權

(*-*)浩
(*-*)浩轉載
2019-09-26 15:37:212905瀏覽

Java執行緒優先權

Java 執行緒優先權

Thread 類別中,使用下列屬性來代表優先權。

private int priority;

我們可以透過 setPriority(int newPriority) 來設定新的優先權,透過 getPriority() 來取得執行緒的優先權。

有些資料透過下面的範例就得出了一個結論:Java 執行緒預設優先權是 5。

public static void main(String[] args) {
    Thread thread = new Thread();
    System.out.println(thread.getPriority());
}
// 打印结果:5

其實這是大錯特錯的,只是看到了表面,看看下面的例子,我們把當前執行緒的優先權改為 4,發現子執行緒 thread 的優先權也是 4。

public static void main(String[] args) {
    Thread.currentThread().setPriority(4);
    Thread thread = new Thread();
    System.out.println(thread.getPriority());
}

// 打印结果:4

這啪啪啪打臉了,如果是線程預設優先級是 5,我們新創建的 thread 線程,沒設定優先級,理應是 5,但實際是 4。我們來看看 Thread 初始化 priority 的原始碼。

Thread parent = currentThread();
this.priority = parent.getPriority();

原來,執行緒預設的優先權是繼承父執行緒的優先權,上面例子我們把父執行緒的優先權設為 4,所以導致子執行緒的優先權也變成 4。

嚴謹一點說,子執行緒預設優先權和父執行緒一樣,Java 主執行緒預設的優先權是 5。

Java 中定義了 3 種優先級,分別是最低優先級(1)、正常優先級(5)、最高優先級(10),程式碼如下所示。 Java 優先權範圍是 [1, 10],設定其他數字的優先權都會拋出 IllegalArgumentException 例外。

/**
 * The minimum priority that a thread can have.
 */
public final static int MIN_PRIORITY = 1;

/**
 * The default priority that is assigned to a thread.
 */
public final static int NORM_PRIORITY = 5;

/**
 * The maximum priority that a thread can have.
 */
public final static int MAX_PRIORITY = 10;

接下來說說執行緒優先權的作用。先看下面程式碼,程式碼邏輯是創建了 3000 個線程,分別是: 1000 個優先權為 1 的線程, 1000 個優先權為 5 的線程,1000 個優先權為 10 的線程。用 minTimes 來記錄 1000 個 MIN_PRIORITY 線程運行時時間戳之和,用 normTimes 來記錄 1000 個 NORM_PRIORITY 線程運行時時間戳之和,用 maxTimes 來記錄 1000 個 MAX_PRIORITY 線程運行時時間戳和線程運行時。透過統計每個優先權的運行的時間戳總和,值越小代表的就是越優先執行。我們運行看看。

public class TestPriority {
    static AtomicLong minTimes = new AtomicLong(0);
    static AtomicLong normTimes = new AtomicLong(0);
    static AtomicLong maxTimes = new AtomicLong(0);

    public static void main(String[] args) {
        List<MyThread> minThreadList = new ArrayList<>();
        List<MyThread> normThreadList = new ArrayList<>();
        List<MyThread> maxThreadList = new ArrayList<>();

        int count = 1000;
        for (int i = 0; i < count; i++) {
            MyThread myThread = new MyThread("min----" + i);
            myThread.setPriority(Thread.MIN_PRIORITY);
            minThreadList.add(myThread);
        }
        for (int i = 0; i < count; i++) {
            MyThread myThread = new MyThread("norm---" + i);
            myThread.setPriority(Thread.NORM_PRIORITY);
            normThreadList.add(myThread);
        }
        for (int i = 0; i < count; i++) {
            MyThread myThread = new MyThread("max----" + i);
            myThread.setPriority(Thread.MAX_PRIORITY);
            maxThreadList.add(myThread);
        }

        for (int i = 0; i < count; i++) {
            maxThreadList.get(i).start();
            normThreadList.get(i).start();
            minThreadList.get(i).start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("maxPriority 统计:" + maxTimes.get());
        System.out.println("normPriority 统计:" + normTimes.get());
        System.out.println("minPriority 统计:" + minTimes.get());
        System.out.println("普通优先级与最高优先级相差时间:" + (normTimes.get() - maxTimes.get()) + "ms");
        System.out.println("最低优先级与普通优先级相差时间:" + (minTimes.get() - normTimes.get()) + "ms");

    }

    static class MyThread extends Thread {

        public MyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            System.out.println(this.getName() + " priority: " + this.getPriority());
            switch (this.getPriority()) {
                case Thread.MAX_PRIORITY :
                    maxTimes.getAndAdd(System.currentTimeMillis());
                    break;
                case Thread.NORM_PRIORITY :
                    normTimes.getAndAdd(System.currentTimeMillis());
                    break;
                case Thread.MIN_PRIORITY :
                    minTimes.getAndAdd(System.currentTimeMillis());
                    break;
                default:
                    break;
            }
        }
    }
}

執行結果如下:

# 第一部分
max----0 priority: 10
norm---0 priority: 5
max----1 priority: 10
max----2 priority: 10
norm---2 priority: 5
min----4 priority: 1
.......
max----899 priority: 10
min----912 priority: 1
min----847 priority: 5
min----883 priority: 1

# 第二部分
maxPriority 统计:1568986695523243
normPriority 统计:1568986695526080
minPriority 统计:1568986695545414
普通优先级与最高优先级相差时间:2837ms
最低优先级与普通优先级相差时间:19334ms

我們一起來分析一下結果。先看看第一部分,最開始執行的線程高優先級、普通優先級、低優先級都有,最後執行的線程也都有各個優先級的,這說明了:優先級高的線程不代表一定比優先權低的執行緒優先執行。也可以換另一種說法:程式碼執行順序跟執行緒的優先權無關。看看第二部分的結果,我們可以發現最高優先權的1000 個執行緒執行時間戳和最小,而最低優先權的1000 個執行緒執行時間戳之和最大,因此可以得知:一批高優先權的執行緒會比一批低優先權的執行緒優先執行,即高優先權的執行緒大機率比低優先的執行緒優先獲得CPU 資源。

各作業系統中真有 10 個執行緒等級麼?

Java 作為跨平台語言,執行緒有 10 個等級,但是映射到不同作業系統的執行緒優先權值不一樣。接下來教大家怎麼在 OpenJDK 原始碼中查各個作業系統中執行緒優先權映射的值。

看到Thread 原始碼,設定執行緒優先權最終呼叫了本機方法setPriority0();

private native void setPriority0(int newPriority);

接著我們在 OpenJDK 的 Thread.c 程式碼中找到 setPriority0() 對應的方法 Thread.c 程式碼中找到 setPriority0() 對應的方法 JVM_SetThreadPriority ;

static JNINativeMethod methods[] = {
    ...
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    ...};

我們根據 JVM_SetThreadPriority 找到 jvm.cpp 中對應的程式碼片段;

JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
  JVMWrapper("JVM_SetThreadPriority");
  // Ensure that the C++ Thread and OSThread structures aren&#39;t freed before we operate
  MutexLocker ml(Threads_lock);
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  if (thr != NULL) {                  // Thread not yet started; priority pushed down when it is
    Thread::set_priority(thr, (ThreadPriority)prio);
  }
JVM_END

根據第3 步驟中的程式碼,我們可以發現關鍵是 java_lang_Thread::set_Priority() 這段程式碼,繼續找 thread.cpp 程式碼中的 set_Priority() 方法;

void Thread::set_priority(Thread* thread, ThreadPriority priority) {
  trace("set priority", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  // Can return an error!
  (void)os::set_priority(thread, priority);
}

以上是Java執行緒優先權的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除