Урок по Java 89: Многопоточность 24: ForkJoinFramework

  Рет қаралды 16,628

Уроки Java

Уроки Java

Күн бұрын

Пікірлер: 47
@dianaaimbetova2895
@dianaaimbetova2895 4 жыл бұрын
Когда для собеседования нужно быстро вспомнить multithreading эти серии видео, самое то! Спасибо!
@barracudashark78
@barracudashark78 4 жыл бұрын
Спасибо. Видео действительно хорошее. Часто нахожу видео этого ютюбера, он один из немногих, кто показывает сугубо практическое применение. Спасибо ему. Тем не менее, в этом видео у парня сразу три ошибки, из-за которых: а. его код не работает, б. он слегка запутывает зрителя. Смотреть нужно обязательно, но принимайте во внимание эти три момента: 1. если он хотел увеличить число до 10 миллиардов прибавляя каждый раз по единице, то в цикле for в 34-й строчке ему нужно было бы написать j +=1; вместо j+=i; (прибавляя растущую i в цикле он несколько раз переполнял переменную long j, и в итоге получил отрицательное значение.) - это на суть fork join не влияет, просто математика. 2. Если бы в методе compute() класса MyFork он бы в ветвлении else{ } написал MyFork firstHalf = new MyFork(from, middle); MyFork secondHalf = new MyFork(middle, to); (
@Alex-gn6xb
@Alex-gn6xb 3 жыл бұрын
со вторым пунктом не согласен. зачем убирать middle+1 ? мы же одно и то же число посчитаем. в третьем пункте почему нельзя просто вернуть return firstHalf.join() + secondHalf.join(); ? в целом, у меня не работает как надо , ищу ошибку почему форк дольше обычного вдвое считает)) тредов 8 up: дичь странная, треды неуправляемы)) ошибка была в блоке if, там не надо считать от j=0, j это наш from и 0 он равен только в одном из потоков полурабочий код: protected Long compute() { if ((to - from)
@Alex-gn6xb
@Alex-gn6xb 3 жыл бұрын
пока никто не опередил отвечу сам себе -) напортачил с whil-ом ты , друг. вот правильный код : if ((to - from) < _ForkJoinPool_lesson.numberToCount / numberAvaliableThreads) { long j = 0; for (long i = from; i < to; i++) { j++; } return j; } else { long middle = (from + to) / 2; FastCountFork firstVal = new FastCountFork(from, middle); FastCountFork secondVal = new FastCountFork(middle, to); firstVal.fork(); secondVal.fork(); return firstVal.join() + secondVal.join(); } на возврате такая разница в милисекундах : start Simple Counting 4728 start Fast Counting 10000000000 1647 вывод: не пишите код после 12 ночи и не будете ошибаться на ровном месте :Р
@АлександрВергун-т9ь
@АлександрВергун-т9ь 3 жыл бұрын
Верно всё говоришь. 1. Я сам немного не понял, какая именно ставилась цель с точки зрения математики: 10млр раз инкрементировать единицу или же просуммировать числа от 1 до 10млрд. Если первое, то да, не нужно делать ' += i;', а если второе, то почему старт идёт с 0, а не с единицы, и исключая саму верхнюю границу?. Да, на работу FJ это не влияет, но в не самой простой теме не хотелось бы стопориться на самом ТЗ. 2. С middle+1 тоже не всё очевидно было. Ещё не успев обдумать всё, как в первом пункте, сразу задался вопросом "а зачем прибавлять единицу-то?" 3. И с этим согласен. Во всех других примерах, что видел, всегда вызывают форки на новых задачах, а затем результат получают через join. Впервые увидел прямой вызов compute, но, к сожалению, не увидел объяснения этому действию. Если это ошибка, то она имхо похожа на прямой вызов метода run у Thread вместо метода start. И в итоге часть параллельной работы просто уходит в никуда.
@АрсенийДьячко
@АрсенийДьячко Жыл бұрын
Вы ещё не упомянули, что ядра процессоров не связанны с потоками. Ядро может спокойно и 8 потоков взять
@mizantropoff
@mizantropoff 7 ай бұрын
@@Alex-gn6xb а ты посмотри на знак в ветке (if) в условии прекращения цикла ( у автора, не у тебя ) Вот от этого знака все и будет зависеть - надо добавлять единичку к мидлу или нет. Кроме того, про j=0 - я думаю ты не прав, меня напрягает твой цикл, я его не проверял - проверь сам на небольшом количестве операций - 4, 5, большое количество операций взято для обоснования - снижение времени работы, а правильность расчета надо проверять на очень небольших цифрах. Кро того, обрати внимание, что автор делает комбинацию рекурсии и fork(), результат рекурсии накапливается в secondValue, которая в свою очередь складывается в каждом форке с его результатом, то есть все это накапливается. Если же использовать два fork(), как у тебя, то результат их сложения тоже должен накапливаться, как это сделал комментатор, под постом которого мы общаемся - result += firstHalf.join() + secondHalf.join();
@chicago21
@chicago21 2 жыл бұрын
Спасибо дядь! Сижу на этой теме, пытался свой пример с решением факториала сделать, в одной строчке накосячил, помогло видео!)
@chingizshidenov547
@chingizshidenov547 7 жыл бұрын
красава спасибо за все видосы,theads все посмотрел
@MrMaksimsergeevich
@MrMaksimsergeevich 6 жыл бұрын
А я уже 2 раза посмотрел. Грядёт третий
@MrMaksimsergeevich
@MrMaksimsergeevich 6 жыл бұрын
Вот и третий...никак не запомню...как же это не просто, видимо буду снова пересматривать
@OlexanderL
@OlexanderL 6 жыл бұрын
Спасибо за труд!!! Очень интересно изложил многопоточность.
@I.Karabadjak
@I.Karabadjak Жыл бұрын
Спасибо! ОЧЕНЬ наглядно. Единственно, корректнее передавать части вот так: long middle = (to - from) / 2; MyFork firstHalf = new MyFork(from, from + middle); firstHalf.fork(); MyFork secondHalf = new MyFork(from + middle + 1 , to); но это, конечно, уже детали не относящиеся к теме!
@mizantropoff
@mizantropoff 7 ай бұрын
Чем корректнее? и та и другая формула дает один результат, но увеличивается количество расчетов, потому что формуда автора сразу нам дает точку, а во втором случае ее еще надо посчитать. Комментаторы, блин... Вам недостаточно того. что автор ни фига не объяснил ничегор?! Еще больше только запутываете
@mizantropoff
@mizantropoff 7 ай бұрын
Как перфекционист замечу, что не отработаны вырожденные случаи, а именно при количестве операций меньше количества потоков будет переполнение стэка, так как условие (to - from
@TooGoolka
@TooGoolka Жыл бұрын
Чтоб на выходе получить 10 ярдов, нужно в инвок from указать 1, а в if j =1, в фор инкремент j
@TooGoolka
@TooGoolka Жыл бұрын
p.s. у меня за 1 сек прогналась рекурсия
@sk0rn982
@sk0rn982 6 жыл бұрын
secondHalf = new MyFork(middle + 1, to) это неправильно, потому что в firstHalf = new MyFork(from, middle) считает в диапазоне не включая middle, поэтому +1 это не правильно, получается само число middle в вычислениях не участвует.
@timurvolkov9262
@timurvolkov9262 4 жыл бұрын
+ переполнение Long убрать (я поставил число поменьше). И тогда всё правильно отрабатывает
@aligator527game6
@aligator527game6 6 жыл бұрын
6:50 - 1C?
@mizantropoff
@mizantropoff 7 ай бұрын
Если кто мучается с цифрами, перестаньте смотреть на время, сначала отдебажьте сам код и поймите его, а для этого лучше передавать небольшое количество операций, чтобы увидеть - результат то верно считается вообще или нет
@dimaster5880
@dimaster5880 7 жыл бұрын
Урок бомба. Очень практично и наглядно.
@mizantropoff
@mizantropoff 7 ай бұрын
Что у Fork() под капотом?
@ShadowKevil
@ShadowKevil Жыл бұрын
в чем смысл fork? почему нельзя просто через new Thread() сделать то же самое?
@ИванРыбаков-с7д
@ИванРыбаков-с7д 6 жыл бұрын
У меня время выполнения задачи не изменяется. Зато при разделении операции на 4 части. Так как у меня 4-х ядерный процессор нагрузка на процессор увеличивается в 4 раза.
@richterDG
@richterDG 7 жыл бұрын
Не понимаю. Вижу, что в этой строчке мы создаем класс System.out.println(pool.invoke(new MyFork(0, nunOfOperations))); Но каким образом вызывается метод protected Long compute() ? Это где то в invoke прописано? И зачем ForkJoinFramework если можно вызвать так System.out.println(new MyFork(0, nunOfOperations).compute());? Вот пример. 1. результат это как у тебя в первом варианте 2. это System.out.println(pool.invoke(new MyFork(0, nunOfOperations))); 3. System.out.println(new MyFork(0, nunOfOperations).compute()); На компьютере ядер: 4 Mon Dec 11 23:28:11 MSK 2017 -4378597037249509888 Mon Dec 11 23:28:30 MSK 2017 Mon Dec 11 23:28:30 MSK 2017 -4378597112249509888 Mon Dec 11 23:28:43 MSK 2017 Mon Dec 11 23:28:43 MSK 2017 -4378597112249509888 Mon Dec 11 23:28:55 MSK 2017 Итого последний быстрее, тогда зачем ForkJoinPool? ))
@ГлебВалерьевич-у6ы
@ГлебВалерьевич-у6ы 2 жыл бұрын
Считает быстро, жалко, что такая херня получается! если поставить сложение, то с 1 потоком (выставленным вручную) результатом будет 10 млрд, а если любое другое количество потоков, то никогда 10 млрд вы не получите из-за неатомарности операции
@АндрейФамилия-я6б
@АндрейФамилия-я6б 3 жыл бұрын
Спасибо!!!
@МаксД-ш3м
@МаксД-ш3м 3 жыл бұрын
а вот тут не понятно.. тут fork() там рекурсия, и теперь всё работает быстрее... Но как именно?
@MaxPrysiazhniuk
@MaxPrysiazhniuk 6 жыл бұрын
Не подскажите почему на 2 ядрах исполнение с фреймом медленее чем без него?
@АлексейЛужников-ъ5е
@АлексейЛужников-ъ5е 4 жыл бұрын
@Пожилой Программист ты клоун?
@Евгений-ч9к2ф
@Евгений-ч9к2ф 6 жыл бұрын
метод fork() - добавляет первую часть диапазона в пул?
@Shodgearo
@Shodgearo 6 жыл бұрын
return firstHalf.join() + secondValue; // Operator '+' cannot be applied to 'java.lang.Object', 'long' Почему у Вас нет ошибок? ) Это так странно... Если я правильно понял... тогда в чем отличие от Callable?
@ВикторШумик-н3й
@ВикторШумик-н3й 10 ай бұрын
Пример того как не надо преподавать!
@romankryvolapov
@romankryvolapov 6 жыл бұрын
100_000_000_000L было 45 стало 26 секунд, работает))
@jijiDwuv
@jijiDwuv 6 жыл бұрын
было 3 стало 2))) лол(4 потока 2 ядра i3 6100)
@sayhellotoroy
@sayhellotoroy 5 жыл бұрын
public class Main { public static void main(String[] args) { System.out.println(new Date()); ForkJoinPool forkJoinPool = new ForkJoinPool(4); System.out.println(forkJoinPool.invoke(new Task(0, Integer.MAX_VALUE))); System.out.println(new Date()); } } class Task extends RecursiveTask { long from; long to; public Task(long from, long to) { this.from = from; this.to = to; } @Override protected Long compute() { if (to - from
@МарияПомазкина-д6э
@МарияПомазкина-д6э 3 жыл бұрын
Очень ценный комментарий, но если бы Вы еще добавили описание этого исправления, было бы просто огонь
@mizantropoff
@mizantropoff 7 ай бұрын
И ты думаешь, совсем лишне объяснить - что делает fork()? Это при том, что ты идешь двумя разными путями почему то.
@serggio88888
@serggio88888 4 жыл бұрын
super.
@antonkuznetsov4978
@antonkuznetsov4978 6 жыл бұрын
Хорошо
@israelmvideoagency1257
@israelmvideoagency1257 5 жыл бұрын
Почему на видео результат с минусом?
@vladimirshiryaev3852
@vladimirshiryaev3852 5 жыл бұрын
Потому что идёт переполнение верхней границы long
@осипакопьянц
@осипакопьянц 7 жыл бұрын
Date d1 = new Date(); Thread.sleep(30);//do something Date d2 = new Date(); long l = d2.getTime()-d1.getTime(); System.out.println("it takes miliseconds : " + l);
@АртёмЮрченко-ж8ъ
@АртёмЮрченко-ж8ъ 7 жыл бұрын
Это параллельное программирование?
@husivm
@husivm 7 жыл бұрын
Да
Выпуск 35. Как работает ForkJoinPool.
23:44
Изучаем Java
Рет қаралды 8 М.
Война Семей - ВСЕ СЕРИИ, 1 сезон (серии 1-20)
7:40:31
Семейные Сериалы
Рет қаралды 1,6 МЛН
Урок по Java 49: Equals and HashCode
38:35
Уроки Java
Рет қаралды 33 М.
Understanding how ForkJoinPool works
13:16
Defog Tech
Рет қаралды 124 М.
Урок по Java 56: Generics - обобщения
43:03
Уроки Java
Рет қаралды 23 М.
Многопоточность в Java: основы
1:23:05
Computer Science Center
Рет қаралды 113 М.
Выпуск 36. ParallelStream, Spliterator и ForkJoinPool.
15:36
Изучаем Java
Рет қаралды 3,6 М.
Java. Методы equals и hashCode.
15:05
Sergey Arkhipov Java Tutorials
Рет қаралды 40 М.
Урок Java 346: Volatile и happens before
18:16
Уроки Java
Рет қаралды 12 М.