Java join не работает

Thread.join не работает

Вызов join() Гарантируется, что текущий поток прекратит выполнение до тех пор, пока не завершится поток, к которому он присоединяется (другими словами, к потоку, к которому он вызывает join()).

Однако в моей программе оба потока выполняются одновременно. Thread1 не ждет, пока Thread2 завершит свое выполнение.

Что не так с моей программой?

public class Launcher1 < public static void main(String[] args) < JoinExample runnable=new JoinExample(); Thread thread1=new Thread(runnable); Thread thread2=new Thread(runnable); thread1.start(); try < Thread.sleep(2000); >catch (InterruptedException e1) < e1.printStackTrace(); >thread2.start(); try < thread2.join(); >catch (InterruptedException e) < e.printStackTrace(); >> > public class JoinExample implements Runnable < public void run()< for(int i=0;i<10;i++)< System.out.println("i:"+i+" "+Thread.currentThread().getName()); try < Thread.sleep(1000); >catch (InterruptedException e) < e.printStackTrace(); >> > > 

2 ответа

Однако в моей программе оба потока выполняются одновременно. Thread1 не ждет, пока Thread2 завершит свое выполнение.

Нет, и не будет — потому что поток 1 не вызывает join , Посмотрите на документы, которые вы цитировали снова:

Вызов join() гарантированно приведет к тому, что текущий поток прекратит выполнение до тех пор, пока поток не присоединится

Другими словами: join() метод не завершается, пока не завершится поток, к которому он вызван.

В вашей программе три потока — два запущены JoinExample.run и «основной» поток, который запускает два других. Вы говорите этому основному потоку дождаться завершения второго потока, но это все. Ваши два JoinExample темы полностью независимы.

Источник

Почему у меня не срабатывает метод join() в потоке?

e58ada4a539e4a449fd7276ba9f0d261.png

Мне нужно вычислить сложное математическое выражение, поэтому я сделал его декомпозицию, чтобы разбить его вычисление на разные потоки.

У меня есть поток №1 и поток №3. В потоке №1 я вычисляю y1 = A*b, а в потоке №3 я вычисляю Y3 = A2C2-B2A2. После этого я хочу передать Y3 в поток №1 для вычисления Y3y1. Для того, чтобы подождать пока завершится поток №3, я в первом потоке вызвал метод thread3.join(), но он у меня почему-то не работает и в итоге во время вычисления Y3y1 выскакивает NullPointerException. Если же я просто усыплю поток №1 на несколько секунд до передачи Y3 в него, то все работает нормально. Так почему же у меня не работает метод join? И можете дать рекомендации по решению задачи и написания кода к ней?

thread1 = new Thread( new Runnable() < @Override public void run() < b = calc_b(); matrixA = generateMatrixA(matrixOrder); y1 = calc_y1(matrixA, matrixOrder); // Не работает! try < thread3.join(); >catch (Exception e) < >// Если сделаю так, то работает. // try < // thread1.sleep(4000); // >catch (InterruptedException e) < // e.printStackTrace(); // >Y3new = Y3; calc_Y3y1(Y3new, y1, matrixOrder); > > ); thread3 = new Thread( new Runnable() < @Override public void run() < matrixA2 = generateMatrixA2(matrixOrder); matrixB2 = generateMatrixB2(matrixOrder); matrixC = generateMatrixC(matrixOrder); Y3 = calc_Y3(matrixA2, matrixB2, matrixC, matrixOrder); >> ); thread1.start(); thread3.start();

Вы просто пишите переменную Y3 в потоке thread3 и просто читаете ее в потоке thread1 — это и есть ошибка.

Читайте также:  Текущий месяц год javascript

Прочитайте что-нибудь про Java concurrency и параллельные вычисления в целом — это довольно сложные темы, и сложность тут, конечно, не в том чтобы навызывать много new Thread().

Возможно в вашем случае проще будет построить логику на модели акторов (на java много разных реализаций, хотя на scala это сделано красивее). Если изучить многопоточность с нуля, то это будет проще в изучении и перспективнее в применении, чем классические подходы.

kostyabakay

А почему конкретно это является ошибкой? Ведь если усыпить немного thread1, то все нормально работает. Я просто не могу понять почему мой join не срабатывает и не ждет завершения thread3, чтобы был доступ к Y3.

Костя Бакай: Я даже не знаю с чего начать объяснять. Вам нужно для начала просто почитать любую книгу про java concurrency про многопоточное програмимирование в целом. Это НАМНОГО сложнее чем вы себе представляеете. Синхроблоки, блокировки, мьютексы, семафоры — вам о чем-нибудь говорят эти слова? Если нет, то просто нельзя вызвыать new Thread().

Костя Бакай: А схема у вас красивая. Думаю, идеально ляжет на модель акторов.
Познакомтесь, например, с Akka — doc.akka.io/docs/akka/snapshot/java/untyped-actors.html

kostyabakay

В моем случае я решил проблему заменой местами стартов потоков, но я конечно же более детально ознакомлюсь с параллелизмом.

Источник

при вызове start() не вызывается метод run(), либо join() не работает.

При вызове start() не вызывается метод run(). Создается ли при этом новая нить — я так и не понял. Или нить создается, но не работает почему-то вызов метода join(). В файлах, что я ввожу в консоль, есть данные, но программа не выполняет метод run(). Соответственно, данные из файлов не читает. А в конце выводит 2 пустые строки. Почему?

1. Разберись, что делает программа.
2. В статическом блоке считай 2 имени файла firstFileName и secondFileName .
3. Внутри класса Solution создай нить public static ReadFileThread , которая реализует
интерфейс ReadFileInterface (Подумай, что больше подходит — Thread или Runnable ).
3.1. Метод setFileName должен устанавливать имя файла, из которого будет читаться содержимое.
3.2. Метод getFileContent должен возвращать содержимое файла.
3.3. В методе run считай содержимое файла, закрой поток. Раздели пробелом строки файла.
4. Подумай, в каком месте нужно подождать окончания работы нити, чтобы обеспечить последовательный вывод файлов.
4.1. Для этого добавь вызов соответствующего метода.

Ожидаемый вывод:
[все тело первого файла]
[все тело второго файла]

(квадратные скобки выводить не нужно)

Статический блок класса Solution должен считывать с консоли имена двух файлов и сохранять их в переменные firstFileName и secondFileName.

Читайте также:  Все оттенки белого html

Источник

Thread.Join не работает, как ожидалось

Я работаю над небольшим примером, используя метод 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

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() 

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

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

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

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

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

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

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

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

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

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

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

Читайте также:  Php скрипт покупки билетов

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

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

Источник

Thread.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

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() 

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

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

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

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

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

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

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

Позволять t2 должно быть завершено до t1 , Начните t2 , вызвать join() в теме.
Тогда начни t1 :

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

Источник

Оцените статью