Многопоточность Java - приоритет потока

Может кто-нибудь объяснить, как приоритет потока работает в 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...");
    }
}

В приведенной выше программе, даже если я изменяю приоритет, я не нахожу разницы в выходе. Также может быть полезным применение в реальном времени того, как приоритет потока может быть полезен. Спасибо.

Ответ 1

Приоритет потока - это всего лишь подсказка для планировщика задач ОС и зависит от базовой ОС. ОС попытается выделить больше ресурсов потоку с высоким приоритетом, но это не гарантирует этого. Поэтому, если ваша программа зависит от приоритетов потоков, вы, в свою очередь, привязываете свою программу к базовой ОС, что плохо.

Из Java параллелизма на практике:

Избегайте соблазна использовать приоритеты потоков, так как они увеличивают зависимость от платформы и могут вызвать проблемы жизнеспособности. Большинство одновременных приложений могут использовать приоритет по умолчанию для всех потоков.

Ответ 2

Приоритет потоков - это только намек на планировщик задач ОС. Планировщик задач будет пытаться выделять больше ресурсов для потока с более высоким приоритетом, однако явных гарантий не существует.

Фактически, это относится не только к Java или JVM. Большинство ОС реального времени используют приоритеты потоков (управляемые или неуправляемые) только наводящим на размышления способом.

Также очень важно, что Priorties отличаются от каждого базового шаблона. Таким образом, вы потеряете свою свободу в java. См. Также это резюме:

Действительно, некоторые уровни приоритета могут отображаться на один и тот же "родной" уровень приоритета. Здесь список (на основе кода Hotspot в OpenJDK 6):

Solaris
1 ⇒ 0
2 ⇒ 32
3 ⇒ 64
4 ⇒ 96
5 - 10 ⇒ 127
Следует отметить, что в Solaris вы не можете повысить приоритет потока выше нормального, только опустите его: значение приоритета для 5 будет таким же, как и любое из более высоких значений.

Linux
1 - 10 ⇒ 4 - -5 (хорошие значения) Следует отметить, что в Linux разные приоритеты потоков в Java отображают различные значения приоритетов на собственном уровне.

Окна
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-приложений, и, на мой взгляд, если вам нужно установить приоритеты, у вас возникнет другая проблема. Как плохой алгоритм, который потребляет много времени процессора и т.д. Я всегда предлагаю не изменять поток java-потоков, так как вы не можете полагаться на него в любом случае. (конечно, есть некоторые сценарии, где это имеет смысл)

Ответ 3

Существует несколько ситуаций, когда установка приоритета для потока полезна, вы просто не должны верить в любые гарантии, которые приходят с такими настройками, как всегда: порядок выполнения с потоками undefined. Если вы считаете, что ваш поток будет выполнен раньше, если вы придадите ему более высокий приоритет, прочитайте вышеприведенное выражение до тех пор, пока это не будет из головы.;)

Вы должны определить приоритет, исходя из того, насколько важно для этого потока увеличить время выполнения по сравнению с другими. Несмотря на то, что система подкладки ничего не гарантирует, она все же может обеспечить преимущества для тех JVM, которые ее поддерживают.

Пример. У вас есть программа, которая выполняет некоторые тяжелые вычисления на основе ввода пользователем в вашем JFrame. Хорошей практикой является то, что эти фоновые потоки имеют низкий приоритет, потому что более важно, чтобы JFrame был отзывчивым, чем работа над расчетом (это займет много времени, чтобы закончить в любом случае, еще несколько миллисов не повредит), ОС по-прежнему будет назначать большинство процессорного времени для потоков с низким приоритетом, если в этом не нуждается что-то более важное. Но тогда хорошо, что этот более важный материал получает приоритет.

Теперь может случиться так, что в некоторых системах параметр приоритета игнорируется, а JFrame снова не отвечает, но тогда это не делает ничего хуже вашего кода, а затем не устанавливает приоритет на низкий уровень.

Ответ 4

Размер задач слишком мал и, вероятно, будет завершен сразу после запуска. Кроме того, если у вас есть "достаточные" ядра процессора, каждый рабочий поток будет выделен одному ядру, поэтому результат будет таким же.

Попробуйте эксперимент в другом контексте, сначала увеличьте размер задачи (например, зациклив от одной тысячи раз до миллиона, без печати), затем увеличьте количество потоков, чтобы превысить количество ядер, которые у вас есть, и третий, создайте свой сначала запускайте потоки, а затем запускайте все потоки (вы не можете запускать их сразу, вам все равно придется их прокручивать).

В моем случае я выбрал 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

Ответ 5

Надеюсь, поможет!

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
}

Ответ 6

 //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;
}