Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

JAVA: задача многопоточность

RostikP Знаток (401), на голосовании 8 месяцев назад
Здравствуйте, изучаю многопоточность, и, решая различные задачи, столкнулся с этим боссом. Честно, не выходит её решить правильно. Суть задания такова: имеется три робота, первый робот выполняет свое задание за 1 минуту, второй за 0.5 минуты, третий за 0.8 минут. Всего роботам вместе надо выполнить 300 задач одновременно и далее вывести на экран количество времени, за которое они выполнили все эти задачи, а также количество задач, выполненных каждым роботом индивидуально.

У меня было множество версий этой программы, но все они неверные, так что не вижу смысла это сюда выкладывать.
Какая была моя логика: выполнить работу это просто сделать инкремент переменной, скажем, total_work_done++, все это делается в цикле while ( total_work_done < 300 ), значит по идее надо сделать total_work_done переменной static, чтобы каждый поток, обращаясь к этой переменной, имел актуальные данные об её значении.
Но какая проблема была - либо один поток полностью выполнял всю работу в независимости от того, был ли метод, в котором есть цикл while, в блоке synchronized, либо выполнял не всю работу, либо один поток выполнял работы больше , чем ему надо сделать. Потому что это чисто математическая задачка с только одним ответом.

По идее как это должно быть, робот1 1 минута, робот2 0.5 минут, робот3 0.8 минут => робот1 1/1 = 1 задача в минуту, робот2 1/0.5 = 2 задачи в минуту, робот3 1/0.8 = 1.25 задач в минуту, тогда всего 1 + 2 + 1.25 = 4.25. 300 / 4.25 ~ 70.5 ~ 71 минута на все задачи (ПО ИДЕЕ), тогда сколько задач у каждого робота: робот1 = 71 * 1 = 71; робот2 71 * 2 = 142 задачи; робот3 = 71 * 1.25 ~ 88 задач.

помогите пожалуйста решить, правда не понимаю, И Я ОЧЕНЬ ХОЧУ РАЗОБРАТЬСЯ. помогите новичку!!!!
Голосование за лучший ответ
Schweik Мыслитель (6138) 9 месяцев назад
 import java.util.concurrent.atomic.AtomicInteger; 

public class Q237147931 {
private static final int JOBS = 30;

private static AtomicInteger jobsLeft = new AtomicInteger(JOBS);

public static void main(String[] args) {
Worker w1 = new Worker(6);
Worker w2 = new Worker(3);
Worker w3 = new Worker(4);
Thread t1 = new Thread(w1, "A");
Thread t2 = new Thread(w2, "B");
Thread t3 = new Thread(w3, "C");
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("\n--------------------");
System.out.println("W1: " + w1.getJobsCount());
System.out.println("W2: " + w2.getJobsCount());
System.out.println("W3: " + w3.getJobsCount());
}

private static class Worker implements Runnable {
private final int waitSeconds;
private int jobsCount = 0;

public Worker(int duration) {
this.waitSeconds = duration;
}

public int getJobsCount() {
return jobsCount;
}

@Override
public void run() {
try {
while (jobsLeft.decrementAndGet() >= 0) {
System.out.print(Thread.currentThread().getName());
System.out.flush();
jobsCount++;
Thread.sleep(waitSeconds * 1000);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.print("\n" + Thread.currentThread().getName() + " finished");
System.out.flush();
}
}
}
RostikPЗнаток (401) 9 месяцев назад
Здравствуйте! Спасибо за решение! Можно уточнить пару моментов?
Вопрос первый:
Каким образом 1 минута, 0.5 минут и 0.8 минут превратились в 6, 3 и 4 соответственно? Мне показалось, что вы просто умножили каждое число на 6 (по идее), но 6 * 0.8 != 4. А также вы вместо 300 задач написали 30 задач. Почему?
Вопрос второй:
Задержка в одну секунду обязательна, или ее можно убрать?
Третий вопрос:
Для чего используется Atomic Integer в этой программе? Почему именно он, а не, к примеру static volatile ?
RostikP Знаток (401) RostikP, Я запустил со значениями, 300 задач и 60, 30 и 48 в секундах, задача очень долго исполняется, можно как-то ускорить решение?
Похожие вопросы