Я работаю над небольшим примером, используя метод join и Thread.sleep, но я не совсем понимаю, как работает поток.

Вот моя программа:

public class Test implements Runnable {

    private String msg;
    private int seconds;

    public Reminder(int sec, String msg) {
        this.sec= sec;
        this.msg= msg;
    }

    public void run() {
        try {
            Thread.sleep(sec* 1000);
            System.out.print(msg+ " ");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Test(1, "one"));
        Thread t2 = new Thread(new Test(3, "two"));

        t2.start();
        t1.start();
        t2.join();
        t1.join();      
    }
}

Поскольку я звоню t2.join(), поток t2 должен завершиться до завершения потока t1.

Поэтому я ожидаю вывод как two one, но получаю вывод как one two

-2
learner 29 Авг 2017 в 15:26

5 ответов

Лучший ответ

Поскольку я вызываю t2.join (), поток t2 должен завершиться до завершения потока t1.

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

Если вы хотите, чтобы t1 запускался после окончания t2, вам нужно вызвать start после окончания t2, и здесь вы можете использовать join

 t2.start();
 t2.join();//main thread will stop here untill t2 is finished 
 t1.start()

Это на самом деле не практично, так как нет реальной разницы между этим и выполнением ваших задач в одном потоке, просто накладные расходы на создание потоков

5
Amer Qarabsa 29 Авг 2017 в 12:28

Поскольку я вызываю t2.join (), поток t2 должен завершиться до завершения потока t1.

Не за что. Вы ждете окончания t2 - но это не мешает другому потоку прогрессировать.

Таким образом, только первая часть вашего предположения верна. Этот код ожидает завершения t2. Это не оказывает никакого влияния на «полноту» t1.

Предположим, у вас есть два бегуна, начинающих в один и тот же момент времени. Вы сидите на финише и наблюдаете только за медленным бегуном. Теперь медленный бегун проходит финишную черту. Почему вы ожидаете, что бегун быстрее все еще будет работать? Он добрался до финиша, пока ты только смотрел на более медленного парня!

2
GhostCat 29 Авг 2017 в 12:31

Поскольку я вызываю t2.join (), поток t2 должен завершиться до завершения потока t1.

Это не тот случай, если t1, который запускается первым, завершил свое выполнение до того, как

t2.join(); выполнен.

Чтобы разрешить t2 завершиться до t1, запустите t2, вызовите join() для него.
Затем начните t1:

t2.start();
t2.join();
t1.start();

Но в некотором роде он побеждает многопоточность, так как каждый поток запускается только после завершения предыдущего

1
davidxxx 29 Авг 2017 в 12:33

Потоки начинают работать сразу после вызова start (). Это включает в себя writeln ().

Join () просто собирает некоторые ресурсы из потока, блокируя, пока поток не будет завершен в процессе.

0
neuhaus 29 Авг 2017 в 12:29

Метод Join заставляет основной поток ждать завершения другого потока, прежде чем он сможет выполнить следующий код после вызова функции join.

Это не имеет никакого отношения к взаимосвязи между двумя или более потоками, которые вы создаете.

0
Debanik Dawn 29 Авг 2017 в 12:31