#java #multithreading
#java #многопоточность
Вопрос:
При выполнении этого кода иногда я замечаю, что поток с минимальным приоритетом выполняется перед потоком с максимальным приоритетом. Кто-нибудь может помочь мне понять, что здесь происходит?
class Test implements Runnable
{
public void run()
{
for(int i=0; i<5; i )
System.out.println(Thread.currentThread().getName());
}
}
class TestMain
{
public static void main(String[] args)
{
Test test = new Test();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setPriority(Thread.MAX_PRIORITY);
t1.setName("Max priority thread");
t2.setPriority(Thread.MIN_PRIORITY);
t2.setName("Min priority thread");
t1.start();
t2.start();
}
}
Иногда я получаю вывод в виде
Min priority thread
Min priority thread
Min priority thread
Min priority thread
Max priority thread
Max priority thread
Max priority thread
Max priority thread
Max priority thread
Min priority thread
и иногда как
Max priority thread
Max priority thread
Max priority thread
Max priority thread
Max priority thread
Min priority thread
Min priority thread
Min priority thread
Min priority thread
Min priority thread
По логике вещей, поток с максимальным приоритетом должен запускаться первым. Но иногда этого не происходит. Если это неизбежно, то как убедиться, что поток с максимальным приоритетом всегда будет запускаться первым?
Комментарии:
1. Потоки не обязательно должны выполняться на основе их приоритета. В конечном счете, это ОС, которая решает, когда выполнять какой поток. Приоритет, который вы даете, — это просто предложение..
2. я думаю, что приоритет потока — это просто рекомендация для базовой ОС. нет никакой гарантии, какой поток действительно будет выполнен первым.
3. @TheLostMind: Тогда есть ли какой-либо способ или алгоритм, который гарантирует, что конкретный поток будет выполнен первым?
4. @NullPointer — я так не думаю..
5. Вы могли бы заставить поток с низким приоритетом ожидать объект синхронизации, который сигнализирует поток с высоким приоритетом, но мы, вероятно, могли бы помочь вам лучше, если бы вы рассказали нам свой вариант использования. При использовании нескольких потоков редко, если вообще когда-либо, имеет значение, в каком порядке они выполняются. Если это так, вам не нужны потоки.
Ответ №1:
Приоритеты — это просто предложение для планировщика. Единственный способ гарантировать, что один конкретный поток выполняется раньше другого, — это сделать это самостоятельно с помощью соответствующего механизма параллелизма, такого как CountDownLatch .
Комментарии:
1. Не знал об
CountDownLatch
этом . Это действительно помогло. Спасибо.
Ответ №2:
попробуйте использовать ExecutorService или ForkJoinPool, чтобы лучше контролировать свои потоки.
и может это вам поможет :
java.util.List<Thread> threads = new ArrayList<>();
for(int i = 0; i < 10; i ){
threads.add(i, new Thread());
}
for(Thread thread : threads){
thread.start();
thread.wait(10);
}
РЕДАКТИРОВАТЬ: пример для ForkJoinPool:
public void start() {
final int parallelism = Runtime.getRuntime().availableProcessors();
final ForkJoinPool forkJoinPool = new ForkJoinPool(parallelism);
final List<ForkJoinTask<Thread>> tasks = new ArrayList<>();
for (int i = 0; i < 100; i ) {
tasks.add(i, newTask(forkJoinPool, i));
tasks.get(i).invoke().start();
}
forkJoinPool.shutdown();
}
private ForkJoinTask<Thread> newTask(final ForkJoinPool pool, final int i) {
return pool.submit(() -> new Thread(() -> {
System.out.println("no " i);
Thread.sleep(50);
})).fork();
}
и вывод:
no 0
no 1
no 2
no 3
no 4
no 5
no 6
no 7
no 8
no 9
no 10
no 12
no 11
no 13
no 14
no 15
no 16
no 17
no 18
no 19
no 20
no 21
no 22
no 23
no 24
no 25
no 26
no 27
no 28
no 29
no 30
no 31
no 32
no 34
no 37
no 38
no 36
no 33
no 35
no 40
no 39
no 41
no 42
no 43
no 44
no 45
no 46
no 47
no 48
no 49
no 50
no 51
no 52
no 53
no 54
no 55
no 56
no 57
no 58
no 59
no 61
no 60
no 62
no 63
no 64
no 65
no 66
no 67
no 69
no 68
no 70
no 72
no 71
no 73
no 74
no 75
no 76
no 78
no 77
no 79
no 80
no 81
no 82
no 84
no 83
no 85
no 86
no 87
no 88
no 89
no 90
no 91
no 92
no 93
no 94
no 96
no 95
no 97
no 98
no 99
Комментарии:
1. @NullPointer было ли это полезно?
2. ДА. Спасибо, что предложили еще один способ.