Вывод чисел последовательно с использованием потоков и лямбд в Java 8

#java #multithreading #java-8 #concurrency #java-threads

#java #многопоточность #java-8 #параллелизм #java-потоки

Вопрос:

Я наткнулся на код для последовательной печати чисел с использованием двух потоков в Java. Вот код

 public class ThreadPrint {
    public static boolean isOdd = false;

    public static void main(String[] args) throws InterruptedException {
        Runnable even = () -> {
            for (int i = 0; i <= 10;)
                if (!isOdd) {
                    System.out.println("Even thread = "   i);
                    i = i   2;
                    isOdd = !isOdd;
                }
        };
        Runnable odd = () -> {
            for (int i = 1; i <= 10;)
                if (isOdd) {
                    System.out.println("odd thread = "   i);
                    i = i   2;
                    isOdd = !isOdd;
                }
        };

        Thread e = new Thread(even);
        Thread o = new Thread(odd);

        e.start();
        o.start();
    }
}
  

Мой вопрос здесь в том, увеличиваю ли я i как i = 2 в самом цикле, например

 for(int i=0; i<10; i =2)
  

Я получаю вывод в виде четного потока = 0, а затем программа останавливает выполнение. Как этот поток и лямбда-выражение выполняют эту работу в более раннем стиле цикла for, где увеличение находится внутри условия, но почему не в самой строке объявления цикла?

Комментарии:

1. Это называется условием гонки: попробуйте увеличить от 10 до 100000 .

2. @MAnouti даже если я доведу его до 10000, он будет работать нормально. Почему это ведет себя по-разному, когда я увеличиваю разными способами (один в строке объявления цикла, а другой в условии в цикле)

Ответ №1:

for (int i = 0; i <= 10;) не увеличивает переменную i , следовательно, действует как бесконечный цикл. Ваш код не потокобезопасен, нет синхронизации при доступе к isOdd между двумя потоками. Однако, поскольку цикл бесконечен, каждый поток в конечном итоге передаст if(isOdd) или if(!isOdd) пять раз и напечатает значения.

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