12

任何人都可以解释线程优先级在java中是如何工作的。这里的困惑是如果java不保证Thread根据其优先级执行,那么为什么要setpriority()使用这个函数。

我的代码如下:

public class ThreadSynchronization implements Runnable{

    public synchronized void run() {
        System.out.println("Starting Implementation of Thread "+Thread.currentThread().getName());
        for(int i=0;i<10;i++)
        {
            System.out.println("Thread "+Thread.currentThread().getName()+" value : "+i);
        }
        System.out.println("Ending Implementation of Thread "+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        System.out.println("Program starts...");
        ThreadSynchronization th1 = new ThreadSynchronization();
        Thread t1 = new Thread(th1);
        t1.setPriority(1);
        synchronized(t1)
        {
            t1.start();
        }

        ThreadSynchronization th2 = new ThreadSynchronization();
        Thread t2 = new Thread(th2);
        t2.setPriority(9);
        synchronized (t2) {
            t2.start(); 
        }

        System.out.println("Program ends...");
    }
}

在上面的程序中,即使我改变了优先级,我也发现输出没有区别。此外,如何使用线程优先级的实时应用程序也会有很大帮助。谢谢。

4

6 回答 6

11

线程优先级只是对 OS 任务调度程序的提示,取决于底层 OS。操作系统会尝试为高优先级线程分配更多资源,但不能保证。因此,如果您的程序依赖于线程优先级,那么您又会将程序绑定到底层操作系统,这很糟糕。

来自Java 并发实践

避免使用线程优先级的诱惑,因为它们会增加平台依赖性并可能导致活性问题。大多数并发应用程序可以为所有线程使用默认优先级。

于 2013-12-02T16:38:38.410 回答
5

线程优先级只是对 OS 任务调度程序的提示。任务调度器只会尝试将更多资源分配给具有更高优先级的线程,但是没有明确的保证。

事实上,它不仅与 Java 或 JVM 有关。大多数非实时操作系统仅以暗示方式使用线程优先级(托管或非托管)。

同样重要的是,每个底层平台的优先级都不同。因此,您有点失去了 java 的平台自由。另请参阅此摘要:

实际上,某些优先级可以映射到相同的“本机”优先级。以下是列表(基于 OpenJDK 6 中的 Hotspot 代码):

Solaris
1 ⇒ 0
2 ⇒ 32
3 ⇒ 64
4 ⇒ 96
5 – 10 ⇒ 127
值得注意的是,在 Solaris 上,您不能将线程优先级提高到高于正常值,只能降低它:5 的优先级值与任何的较高值。

Linux
1 – 10 ⇒ 4 – -5(不错的值) 值得注意的是,在 Linux 上,Java 中不同的线程优先级确实映射到本机级别的不同优先级值。

Windows
1 – 2 ⇒ THREAD_PRIORITY_LOWEST
3 – 4 ⇒ THREAD_PRIORITY_BELOW_NORMAL
5 – 6 ⇒ THREAD_PRIORITY_NORMAL
7 – 8 ⇒ THREAD_PRIORITY_ABOVE_NORMAL
9 – 10 ⇒ THREAD_PRIORITY_HIGHEST

我开发了很多多线程 Java 应用程序,在我看来,如果您必须设置广告优先级,那么您还有另一个问题。就像一个消耗大量 cpu 时间的糟糕算法等等......我总是建议不要更改 java 线程优先级,因为无论如何你都不能依赖它。(当然有一些场景是有意义的)

于 2013-12-02T16:37:33.053 回答
1

在几种情况下,为 Thread 设置优先级很有用,您只是不能像往常一样开始相信来自此类设置的任何保证:线程的执行顺序是未定义的。如果你认为如果你给它更高的优先级,你的线程会更早完成,请再次阅读上面的声明,直到你想不通为止。;)

您应该根据此线程与其他线程相比获得执行时间的重要性来定义优先级。即使底层系统没有任何保证,它仍然可以为那些支持它的 JVM 提供好处。

示例:您有一个程序根据 JFrame 中的用户输入进行一些繁重的计算。将这些后台线程设置为低优先级是一个好习惯,因为 JFrame 的响应比计算工作更重要(无论如何这将需要很长时间才能完成,多几毫秒不会有什么坏处) . 操作系统仍会将大部分 CPU 时间分配给低优先级线程,除非更重要的事情需要它。但是,这个更重要的东西得到优先级是件好事。

现在可能会发生在某些系统上优先级设置被忽略并且 JFrame 再次无响应的情况,但是这对您的代码没有更糟的影响,然后首先没有将优先级设置为低。

于 2013-12-02T17:21:30.210 回答
1

任务的大小太小,可能会在开始后立即完成。此外,如果您有“足够”的 CPU 内核,每个工作线程将分配给一个内核,因此结果将是相同的。

在不同的上下文中尝试实验,首先增加任务大小(例如通过循环一千次到一百万次,不打印)然后增加线程数以超过您拥有的内核数,第三,首先创建您的线程并然后启动所有线程(你不能一次启动它们,你仍然需要循环它们)。

就我而言,我选择了 10 个线程,因为我在具有两个超线程内核的处理器上运行代码,同时运行四个线程。

我对您的示例的更改:

public class ThreadPriority implements Runnable {

    public synchronized void run() {
        System.out.println("Starting Implementation of Thread " + Thread.currentThread().getName());
        float s = 0;
        for (int i = 0; i < 1000; i++)
            for (int k = 0; k < 1000000; k++)
                s += k;
        System.out.println("Ending Implementation of Thread " + Thread.currentThread().getName() + " " + s);
    }

    Thread t;

    public ThreadPriority(String name, int prio) {
        t = new Thread(this);
        t.setName(name);
        t.setPriority(prio);
    }

    public void start() {
        synchronized (t) {
            t.start();
        }
    }

    public static void main(String[] args) {
        System.out.println("Program starts...");
        ThreadPriority[] th = new ThreadPriority[10];
        for (int i = 0; i < th.length; i++) {
            th[i] = new ThreadPriority("T" + i, i / 2 + 1);
        }

        for (ThreadPriority tp : th)
            tp.start();

        System.out.println("Program ending, wait for all the threads to complete");
    }
}

结果是:

Program starts...
Starting Implementation of Thread T0
Starting Implementation of Thread T9
Starting Implementation of Thread T8
Starting Implementation of Thread T5
Program ending, wait for all the threads to complete
Starting Implementation of Thread T4
Starting Implementation of Thread T6
Starting Implementation of Thread T7
Starting Implementation of Thread T2
Starting Implementation of Thread T3
Starting Implementation of Thread T1
Ending Implementation of Thread T6 1.7592186E13
Ending Implementation of Thread T7 1.7592186E13
Ending Implementation of Thread T4 1.7592186E13
Ending Implementation of Thread T8 1.7592186E13
Ending Implementation of Thread T9 1.7592186E13
Ending Implementation of Thread T5 1.7592186E13
Ending Implementation of Thread T2 1.7592186E13
Ending Implementation of Thread T0 1.7592186E13
Ending Implementation of Thread T1 1.7592186E13
Ending Implementation of Thread T3 1.7592186E13

正如你所看到的,低数量的线程往往会更晚结束,因为高数量的线程具有更高的优先级。通过将天平倒置:

    for (int i = 0; i < th.length; i++) {
        th[i] = new ThreadPriority("T" + i, 9 - i / 2 );
    }

低数量的线程比高数量的线程完成得更快。一些线程甚至在其他线程启动之前就完成了,因为它们与调用程序相比具有更高的优先级:

Program starts...
Starting Implementation of Thread T0
Starting Implementation of Thread T1
Starting Implementation of Thread T2
Starting Implementation of Thread T3
Program ending, wait for all the threads to complete
Ending Implementation of Thread T2 1.7592186E13
Ending Implementation of Thread T3 1.7592186E13
Ending Implementation of Thread T0 1.7592186E13
Ending Implementation of Thread T1 1.7592186E13
Starting Implementation of Thread T9
Starting Implementation of Thread T4
Starting Implementation of Thread T8
Starting Implementation of Thread T7
Starting Implementation of Thread T5
Starting Implementation of Thread T6
Ending Implementation of Thread T4 1.7592186E13
Ending Implementation of Thread T5 1.7592186E13
Ending Implementation of Thread T7 1.7592186E13
Ending Implementation of Thread T8 1.7592186E13
Ending Implementation of Thread T9 1.7592186E13
Ending Implementation of Thread T6 1.7592186E13
于 2016-05-11T13:12:15.557 回答
-1

希望能帮助到你!

package priority;

public class ThreadPriorityApp {

    // Note : Thread priority may not be supported in some OS due to underlying task scheduler at OS level

    /**
     * MyThread is an inner class implementing Thread functionality
     *
     */
    class MyThread extends Thread {

        public MyThread(String threadName) {
            super(threadName);
        }
        public void run() {
            System.out.println("Running  thread - " + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {

        //If priority is not set then main priority is set to threads created inside main thread - Parent to child
        // Main thread priority - 5, is set to Thread 1 and Thread 2, if not manually assigned (commenting Line #34 and #35)
        System.out.println("Main thread priority - " + Thread.currentThread().getPriority());

        ThreadPriorityApp threadPriorityApp = new ThreadPriorityApp();

        //We are creating two threads
        MyThread th = threadPriorityApp.new MyThread("Thread 1");
        MyThread th2 = threadPriorityApp.new MyThread("Thread 2");

        // Range 1 to 10 - 10 being given as MAX Priority
        th.setPriority(Thread.MIN_PRIORITY);
        th2.setPriority(Thread.MAX_PRIORITY);

        //We have started Thread 1 first and then Thread 2 later
        th.start();
        th2.start();

//      Possible Outcomes(1) (With Priority - Line #34 and #35) :
//      Running  thread - Thread 2
//      Running  thread - Thread 1


//      Possible Outputs(2) : (Without Priority - commenting Line #34 and #35)
//      (1) Running  thread - Thread 1
//          Running  thread - Thread 2
//      OR
//      (2) Running  thread - Thread 2
//          Running  thread - Thread 1

    }

    //Happy coding -- Parthasarathy S
}
于 2019-07-13T14:57:39.450 回答
-2
 //The iterative and recursive with memorize both shows count as 1424 for digits of length ten starting with 1.
 int[][] b = {{4,6},{6,8},{7,9},{4,8},{0,3,9},{},{1,7,0},{2,6},{1,3},{2,4}};
 public int countIterative(int digit, int length) {
    int[][] matrix = new int[length][10];
    for(int dig =0; dig <=9; dig++){
          matrix[0][dig] = 1;
    }
    for(int len = 1; len < length; len++){
        for(int dig =0; dig <=9; dig++){
          int sum = 0;
          for(int i : b[dig]){
            sum += matrix[len-1][i];
          }
          matrix[len][dig] = sum;
        }
    }
    return matrix[length-1][digit];
}
public int count(int index, int length, int[][] matrix ){
    int sum = 0;
    if(matrix[length-1][index] > 0){
       return matrix[length-1][index];
    }
    if( length == 1){
        return 1;
    }
    for(int i: b[index] )  {
         sum += count(i, length-1,matrix);
    }
    matrix[length-1][index] = sum;
    return sum;
}
于 2016-04-04T14:54:08.120 回答