хм ... нельзя ссылку на git вставить, коммент удаляется. Небольшой код на основе SynchronousQueue, позволяет добавлять любое количество потоков, выполняющихся по схеме 1,2,3,1,2,3,...
а зачем в первом примере в конце join() если он уже в лябде вызова потока? а во второй задаче можно просто преключаться через Semaphore.aquire() / release()
@@voynere ну когда я например собесился на джуна, то вопросы (не текстовые) по многопоточке были в некоторых компаниях. Это был 20 год. Да и Джуну всё-таки хорошо бы хоть какую-то базу по этому иметь
например, порнохаб ввел защиту от скачивания файлов и теперь передает m3u8 файлы, который содержит ссылку на segment файл. задача - собрать исходный ролик, путем объединения всех сегментов в mp4 файл. ограничения скорость интернета 100кб, у процессора 2 ядра, оперативная память 2Гб. размер сегмента 8кб, а скорость декодировки одного сегмента 20мс.
почему бы не рассмотреть CyclicBarrier, а вы точно уверены что не volatile флаги всегда будут отрабатывать как надо в syncronized? Может лучше сделать их AtomicBoolean или volatile?
@@alexandr7686 а в чем проблема реордеринга ? Просто нужно правильно синхронизировать тот код, кот-ый будет выполняется многими потоками и всё будет ок, т.к. все эти реордеринги будут не видны в других потоках. Если эффект реордеринга виден в другом потоке, то значит, что код некорректно синхронизован
Как то в первой всё усложнено, можно проще: Thread third = new Thread( () -> foo.third() ); Thread second = new Thread( () -> foo.second() ); Thread first = new Thread( () -> foo.first() ); third.start(); third.join(); second.start(); second.join(); first.start(); first.join();
хм ... нельзя ссылку на git вставить, коммент удаляется. Небольшой код на основе SynchronousQueue, позволяет добавлять любое количество потоков, выполняющихся по схеме 1,2,3,1,2,3,...
Пришли в телеграмм @parsentev
а зачем в первом примере в конце join() если он уже в лябде вызова потока? а во второй задаче можно просто преключаться через Semaphore.aquire() / release()
В этом видео я разбираю решение тестового задания по многопоточности из компании Сбер.
Стань программистом с www.job4j.ru
А это на какую позицию? Джун, мидл ?
@@Max-wn2gdмногопоточность уже на Джуна требуют)
Думаю, что мидл. От джунов требуют ООП, Коллекции, SQL. А тут все же уже тонкости.
@@voynere ну когда я например собесился на джуна, то вопросы (не текстовые) по многопоточке были в некоторых компаниях. Это был 20 год. Да и Джуну всё-таки хорошо бы хоть какую-то базу по этому иметь
нужна ссылка на проект, иначе трудно воспринимать
Привет Петр, спасибо. Я попробовал сделать через 2 BlockingQueue, в который один пишет, а другой ждет. Есть еще задачки? ))
например, порнохаб ввел защиту от скачивания файлов и теперь передает m3u8 файлы, который содержит ссылку на segment файл. задача - собрать исходный ролик, путем объединения всех сегментов в mp4 файл.
ограничения скорость интернета 100кб, у процессора 2 ядра, оперативная память 2Гб. размер сегмента 8кб, а скорость декодировки одного сегмента 20мс.
почему бы не рассмотреть CyclicBarrier, а вы точно уверены что не volatile флаги всегда будут отрабатывать как надо в syncronized? Может лучше сделать их AtomicBoolean или volatile?
Переменные в синхронайзд блоке будут ок отрабатывать т.к. такого рода блоки подчиняются правилу "happens before".
Попробуйте тоже решить ее. Я посмотрю ваше решение. Давайте вместе.
@@Max-wn2gd synchronized гарантирует лок но не гарантирует защиту от реордеринга, если я не ошибаюсь. Поэтому нужен volatile
@@alexandr7686 а в чем проблема реордеринга ? Просто нужно правильно синхронизировать тот код, кот-ый будет выполняется многими потоками и всё будет ок, т.к. все эти реордеринги будут не видны в других потоках. Если эффект реордеринга виден в другом потоке, то значит, что код некорректно синхронизован
И где ж в Сбере такие задания дают?
Это сберподстава, чтобы больше просмотров было. В сбер берут всех, только скажи что программист )).
спасибо большое
Это тестовое задание на джуна или выше?
А они его всем дают.
Как то в первой всё усложнено, можно проще: Thread third = new Thread(
() -> foo.third()
);
Thread second = new Thread(
() -> foo.second()
);
Thread first = new Thread(
() -> foo.first()
);
third.start();
third.join();
second.start();
second.join();
first.start();
first.join();
😂
А где тут многопоточность?
AtomicBoolean bFirst = new AtomicBoolean(true);
...
var first = new Thread(() -> {
int count = 1;
while (count {
int count = 1;
while (count
Возможный вариант, но yield же не гарантирует, что нить переключит контекст.
@@job4j пропустит другую. Можно sleep(10) тоже работает
package org.example;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws InterruptedException {
temp temp = new temp();
CountDownLatch countDownLatch = new CountDownLatch(2938747);
CountDownLatch countDownLatch2 = new CountDownLatch(1);
var t1 = new Thread(() -> {
synchronized (temp) {
countDownLatch2.countDown();
temp.q1("first");
countDownLatch.countDown();
temp.waitqwe(temp);
temp.doSomeWith1Thread("first", countDownLatch, temp);
if(countDownLatch.getCount() % 2 != 0) {
temp.q1("first");
countDownLatch.countDown();
temp.notify();
}
}
});
var t2 = new Thread(() -> {
asdwaitlatch2(countDownLatch2);
synchronized (temp) {
temp.doSomeWith2Thread("double", countDownLatch, temp);
temp.doSomeWith2Thread("double", countDownLatch, temp);
if(countDownLatch.getCount() % 2 == 0) {
temp.q1("double");
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
temp.asd.forEach(System.out::println);
}
static void asdwaitlatch2(CountDownLatch countDownLatch2) {
try {
countDownLatch2.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
class temp {
List asd = new CopyOnWriteArrayList();
void q1(String qwe) {
asd.add(qwe);
}
void doSomeWith1Thread(String name, CountDownLatch countDownLatch, temp temp) {
if(countDownLatch.getCount() % 2 != 0) {
temp.q1(name);
countDownLatch.countDown();
temp.notify();
temp.waitqwe(temp);
}
}
void doSomeWith2Thread(String name, CountDownLatch countDownLatch, temp temp) {
if(countDownLatch.getCount() % 2 == 0) {
temp.q1(name);
countDownLatch.countDown();
temp.notify();
temp.waitqwe(temp);
}
}
void waitqwe(temp temp) {
try {
temp.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
думаю даже первый летч излишний, можно просто AtomicInteger count в temp поставить
package org.example;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) throws InterruptedException {
temp temp = new temp();
CountDownLatch countDownLatch2 = new CountDownLatch(1);
var t1 = new Thread(() -> {
synchronized (temp) {
countDownLatch2.countDown();
temp.q1("first");
temp.count.incrementAndGet();
temp.waitqwe(temp);
temp.doSomeWith1Thread("first", temp.count, temp);
if(temp.count.get() % 2 != 0) {
temp.q1("first");
temp.count.incrementAndGet();
temp.notify();
}
}
});
var t2 = new Thread(() -> {
asdwaitlatch2(countDownLatch2);
synchronized (temp) {
temp.doSomeWith2Thread("double", temp.count, temp);
temp.doSomeWith2Thread("double", temp.count, temp);
if(temp.count.get() % 2 == 0) {
temp.q1("double");
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
temp.asd.forEach(System.out::println);
}
static void asdwaitlatch2(CountDownLatch countDownLatch2) {
try {
countDownLatch2.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
class temp {
List asd = new CopyOnWriteArrayList();
AtomicInteger count = new AtomicInteger(2938747);
void q1(String qwe) {
asd.add(qwe);
}
void doSomeWith1Thread(String name, AtomicInteger countDownLatch, temp temp) {
if(countDownLatch.get() % 2 != 0) {
temp.q1(name);
countDownLatch.decrementAndGet();
temp.notify();
temp.waitqwe(temp);
}
}
void doSomeWith2Thread(String name, AtomicInteger countDownLatch, temp temp) {
if(countDownLatch.get() % 2 == 0) {
temp.q1(name);
countDownLatch.decrementAndGet();
temp.notify();
temp.waitqwe(temp);
}
}
void waitqwe(temp temp) {
try {
temp.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
package org.example;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
List futures = new ArrayList();
temp temp = new temp();
for (int i = 0; i < 11; i++) {
if (i % 2 == 0) {
futures.add(CompletableFuture.supplyAsync(() -> "first"));
} else {
futures.add(CompletableFuture.supplyAsync(() -> "second"));
}
}
futures.forEach(completableFuture -> {
try {
completableFuture.get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
});
futures.forEach(e -> {
try {
temp.asd.add(e.get());
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
});
temp.asd.forEach(System.out::println);
}
}
class temp {
List asd = new CopyOnWriteArrayList();
}
ну или вообще вот так сделать
Спасибо. Попросите GPT теперь решить и сравните со своим решение.
@@job4j зачем? он скинул костыли с Thread.sleep