Что-то изменилось с Java8 на Java9 за кулисами в Thread Scheduler.Я пытаюсь сузить изменения в приведенной ниже программе.
Ниже программа порождает 3 потока, которые работают параллельно и синхронно, правильно проходя блокировку монитора, печатая
Aa0Bb1Cc2Dd3.......Zz25
Текущий код уже работаетхорошо во всех версиях Java, и я не ищу каких-либо оптимизаций.
Я использовал Object.notifyAll () перед прохождением блокировки с помощью Object.wait () (это может быть не всегда правильно, но в этой ситуации это не имело значения в Java 1.8).Вот почему есть две версии этого кода: версия 1 и версия 2.
версия 1 отлично работает во всех версиях Java (Java8 и более ранние версии, Java9 и более поздние версии).Но не версия 2. Когда вы комментируете версию 1 и не комментируете версию 2 для экспертизы, как это
//obj.wait();//version 1
obj.notifyAll();obj.wait();//version 2
Она работает точно так же в Java8, что и в Java9 и более поздних версиях JDK - нет.Он не может захватить блокировку или захватывает блокировку, но условие уже перевернуто, и нет очереди нити.
(например, в, скажем, оцепенелом потоке завершил свою работу, и теперь только поток, который может захватить блокировку и продолжить, является ThreadCapital, но каким-то образом isCapital был превращен в ложь - это просто предположение, не может доказать это или нетуверен, что это даже происходит)
У меня мало опыта работы с потоками, поэтому я уверен, что не использовал блокировку на мониторе или даже если бы она у меня была, она должна отражать то же самое во всех JDK.если что-то не изменилось в Java9 и более поздних версиях.Что-то изменилось внутри планировщика потоков или что-то в этом роде?
package Multithreading_misc;
public class App {
public static void main(String[] args) throws InterruptedException {
SimpleObject obj = new SimpleObject();
ThreadAlphaCapital alpha = new ThreadAlphaCapital(obj);
ThreadAlphaSmall small = new ThreadAlphaSmall(obj);
ThreadNum num = new ThreadNum(obj);
Thread tAlpha = new Thread(alpha);
Thread tSmall = new Thread(small);
Thread tNum = new Thread(num);
tAlpha.start();
tSmall.start();
tNum.start();
}
}
class ThreadAlphaCapital implements Runnable{
char c = 'A';
SimpleObject obj;
public ThreadAlphaCapital(SimpleObject obj){
this.obj = obj;
}
@Override
public void run() {
try {
synchronized (obj) {
while(c < 'Z')
{
if(!obj.isCapitalsTurn || obj.isNumsTurn)
{
obj.wait();//version 1
//obj.notifyAll();obj.wait();//version 2
}
else
{
Thread.sleep(500);
System.out.print(c++);
obj.isCapitalsTurn = !obj.isCapitalsTurn;
obj.notifyAll();//version 1
//obj.notifyAll();obj.wait();//version 2
}
}
obj.notifyAll();
}
}
catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
class ThreadAlphaSmall implements Runnable{
char c = 'a';
SimpleObject obj;
public ThreadAlphaSmall(SimpleObject obj){
this.obj = obj;
}
@Override
public void run() {
try {
synchronized (obj) {
while(c < 'z')
{
if(obj.isCapitalsTurn || obj.isNumsTurn)
{
obj.wait();//version 1
//obj.notifyAll();obj.wait();//version 2
}
else
{
Thread.sleep(500);
System.out.print(c++);
obj.isCapitalsTurn = !obj.isCapitalsTurn;
obj.isNumsTurn = !obj.isNumsTurn;
obj.notifyAll();//version 1
//obj.notifyAll();obj.wait();//version 2
}
}
obj.notifyAll();
}
}
catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
class ThreadNum implements Runnable{
int i = 0;
SimpleObject obj;
public ThreadNum(SimpleObject obj){
this.obj = obj;
}
@Override
public void run() {
try {
synchronized (obj) {
while(i < 26)
{
if(!obj.isNumsTurn)
{
obj.wait();//version 1
//obj.notifyAll();obj.wait();//version 2
}
else
{
Thread.sleep(500);
System.out.print(i++);
obj.isNumsTurn = !obj.isNumsTurn;
obj.notifyAll();//version 1
//obj.notifyAll();obj.wait();//version 2
}
}
obj.notifyAll();
}
}
catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
class SimpleObject{
public boolean isNumsTurn = false;
public boolean isCapitalsTurn = true;
}
Несколько замечаний:
Это выполняется из модуля UnNamed при запуске из Java9 и более поздних версий
Я не говорю, что это происходит только с 3 потоками, просто приведу пример.Кстати, он (с переоценкой) работает нормально для двух потоков для всех версий Java