Если join блокирует основной поток, почему он не блокируется в цикле? - PullRequest
1 голос
/ 28 июня 2019

Метод join () экземпляра Thread может использоваться для «соединения» начала выполнения потока с концом выполнения другого потока, чтобы поток не запустился, пока не закончится другой поток. Если join () вызывается для экземпляра Thread, текущий работающий поток будет блокироваться до тех пор, пока экземпляр Thread не завершит выполнение

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

public class MultiThreading implements Runnable {


private int name;
public MultiThreading(int number) {
    name =number;
}

@Override
public void run() {
    for (int i = 0; i <= 10; i++ ) {

           System.out.println("Thread number :" + name +" Printed value "+i);

        try {
            Thread.sleep(100);
        } catch (final InterruptedException e) {
            return;
        }
    }
}


public static void main(String[] args) throws InterruptedException {

    final Thread[] workers = new Thread[3];
    for (int i = 0; i < nthreads; ++i) {
        workers[i] = new Thread(new MultiThreading(i));
    }
    for (final Thread t : workers) {
        t.start();

    }

    for (final Thread t : workers) {
        t.join();
        System.out.println("Thread joind to main thread : " + t.getName());
    }
    System.out.println("Main thread ends");
}

}

В приведенном выше коде, если первый поток присоединяется, тогда основной поток должен быть заблокирован, и он не должен позволять присоединиться другому потоку (пока присоединенный поток не завершит выполнение метода run). Но все потоки соединены параллельно. Вывод как -

Thread number :0 Printed value 0
Thread number :1 Printed value 0
Thread number :2 Printed value 0
Thread number :0 Printed value 1
Thread number :1 Printed value 1
Thread number :2 Printed value 1
Thread number :0 Printed value 2
Thread number :1 Printed value 2
Thread number :2 Printed value 2
Thread number :0 Printed value 3
Thread number :1 Printed value 3
Thread number :2 Printed value 3
Thread number :0 Printed value 4
Thread number :1 Printed value 4
Thread number :2 Printed value 4
Thread number :1 Printed value 5
Thread number :0 Printed value 5
Thread number :2 Printed value 5
Thread number :0 Printed value 6
Thread number :1 Printed value 6
Thread number :2 Printed value 6
Thread number :1 Printed value 7
Thread number :0 Printed value 7
Thread number :2 Printed value 7
Thread number :0 Printed value 8
Thread number :1 Printed value 8
Thread number :2 Printed value 8
Thread number :1 Printed value 9
Thread number :0 Printed value 9
Thread number :2 Printed value 9
Thread number :1 Printed value 10
Thread number :0 Printed value 10
Thread number :2 Printed value 10
Thread joind to main thread : Thread-0
Thread joind to main thread : Thread-1
Thread joind to main thread : Thread-2
Main thread ends

1 Ответ

2 голосов
/ 28 июня 2019

Прежде всего:

Метод join () экземпляра Thread можно использовать для «соединения» начала выполнения потока с концом выполнения другого потока

Это неправильное представление: это не имеет ничего общего с начиная с Threads.Объединение делает только это: поток , работающий будет ждать окончания другого потока.

Когда вы выполните someThread.join(), поток, вызывающий этот метод, будет ждать, пока не завершится someThread!

Но все потоки соединены параллельно.

Да, потому что все они сделаны.

Ваши потоки делают все одно и то же, поэтому, кроме нескольких наносекунд здесь или там (которые в основном недействительны из-за того, что запись в System.out эффективно синхронизирует вещи в любом случае) им всем нужно одинаковое количествовремя.

Итак, когда вы присоединитесь к первому потоку ... два других потока будут завершены.Таким образом, первый вызов join() заставляет «основной» поток ждать завершения первого потока, а последующие вызовы происходят «мгновенно», потому что эти потоки также завершены.

Чтобы отложить вещи, сделайте количество циклов параметром вашего MultiThreading класса, а затем убедитесь, что вашим потокам потребуется различное количество времени.Если Thread-0 делает 10 циклов, а Thread-1 - 20, а Thread-2 - 30, вы увидите, что каждое соединение действительно ожидает завершения соответствующего потока.

Короче говоря: вы запускаете все ваши потоки сразу, поэтому они сразу же начинают работать параллельно.Последующий вызов объединения просто задерживает выполнение потока main до тех пор, пока не завершится каждый из рабочих потоков.

...