Thread2 ожидает завершения Thread1, чтобы начать Проблема? Java - PullRequest
0 голосов
/ 04 апреля 2020

Итак, у меня есть простой код, который я хочу вывести значение I 10 раз с Thread1, после этого 10 раз с Thread2 и в конце вывести счетчик (он должен быть 20). Я использую ".join ()", но в результате выполняются случайные времена Thread1 и Thread2, а затем сумма верна. Как можно распечатать сначала все нити 1 л oop, а затем протектор 2 ??

class MyClass extends Thread {  

     public static synchronized void incount() {
         SimpleThreads.count++;
     } 
        public void run() { 

            for(int i=0; i<10; i++) { 
                    incount();  
                    System.out.println(Thread.currentThread().getId()+" value : " + i);
            }
        }           
    }

public class SimpleThreads {

     static int count=0;

    public static void main(String[] args) {

        MyClass thread1 =new MyClass();
        MyClass thread2 =new MyClass();

        thread1.start(); 
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(" Sum : "+count);
    }
}

Результат:

11 value : 0
10 value : 1
11 value : 1
10 value : 2
11 value : 2
10 value : 3
11 value : 3
11 value : 4
11 value : 5
11 value : 6
11 value : 7
11 value : 8
11 value : 9
10 value : 4
10 value : 5
10 value : 6
10 value : 7
10 value : 8
10 value : 9
 Sum : 20

Ответы [ 2 ]

3 голосов
/ 04 апреля 2020

Вы запускаете Thread2 перед вызовом join() для thread1.
Именно поэтому оба ваших потока в основном работают одновременно, и ваше объединение не влияет на run() любых других двух потоков.

Попробуйте изменить свой старт и присоединить код вызова к чему-то вроде этого;

try{
    thread1.start();
    thread1.join();
    thread2.start();
}

В этом случае вам не нужно вызывать join() в потоке 2.

2 голосов
/ 04 апреля 2020

Если вы хотите, чтобы thread2 запускался после завершения thread1, тогда, конечно, вы можете просто подождать, пока thread1 завершится, и затем запустить thread2. Но тогда какой смысл использовать потоки?

Если вы хотите запустить thread1 и thread2 одновременно и все еще иметь thread2, ожидайте завершения thread1, вы можете использовать один из них. из Java множества утилит для параллелизма , таких как Семафор

Приведенный ниже код демонстрирует использование Semaphore. Как вы можете видеть, как и в коде в вашем вопросе, оба потока - thread1 и thread2 - запускаются одновременно. В методе run() класса MyClass код пытается получить семафор. Метод acquire() заблокирует, то есть не вернет, пока не получит семафор. Следовательно, первый поток, которому удастся получить семафор, будет работать, в то время как другой поток будет ждать, пока первый поток освободит семафор. Обратите внимание, что я создаю семафор только с одним разрешением, что означает, что только один поток может получить семафор одновременно. Если вы измените 1 на 2 при вызове конструктора Semaphore, вы получите то же поведение, что и в исходном коде в вашем вопросе, т.е. оба потока будут работать одновременно, потому что оба могут сразу получить семафор.

Обратите также внимание, что, поскольку я использую семафор, мне совсем не нужно вызывать Thread.join(), чтобы один поток ожидал завершения другого, но так как вы хотите напечатать " sum "в" основном "потоке," основному "потоку нужно ждать, но ему нужно только дождаться завершения второго потока.

Вот код:

import java.util.concurrent.Semaphore;

class MyClass extends Thread {
    private Semaphore semaphore;

    public MyClass(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    public static synchronized void incount() {
        SimpleThreads.count++;
    }

    public void run() {
        try {
            semaphore.acquire();
            for (int i = 0; i < 10; i++) {
                incount();
                System.out.println(Thread.currentThread().getId() + " value : " + i);
            }
        }
        catch (InterruptedException xInterrupted) {
            xInterrupted.printStackTrace();
        }
        finally {
            semaphore.release();
        }
    }
}

public class SimpleThreads {

    static int count = 0;

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(1);

        MyClass thread1 = new MyClass(semaphore);
        MyClass thread2 = new MyClass(semaphore);

        thread1.start();
        thread2.start();
        try {
            thread2.join();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(" Sum : " + count);
    }
}

А вот вывод, полученный при запуске вышеуказанного кода:

13 value : 0
13 value : 1
13 value : 2
13 value : 3
13 value : 4
13 value : 5
13 value : 6
13 value : 7
13 value : 8
13 value : 9
14 value : 0
14 value : 1
14 value : 2
14 value : 3
14 value : 4
14 value : 5
14 value : 6
14 value : 7
14 value : 8
14 value : 9
 Sum : 20
...