Здравствуйте, есть задание создать конвейер, где каждый рабочий это 1 поток. Нужно сделать так чтобы потоки обрабатывали предметы. Написал вот такой код, но он очень не стабильный. Выдает правильный результат через некоторое кол-во запусков. Посоветуйте, что можно сделать (sleep нельзя использовать)
public class Worker extends Thread{
private int id;
private static int itemCounter;
private int current = 1;
private static Worker[] workers;
private boolean done = false;
private Worker(String name, int id) {
setName(name);
this.id = id;
}
@Override
public void run() {
try {
if (id != 0) {
synchronized (this) {
wait();
}
}
while (current <= itemCounter) {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " processing " + current + " item");
current++;
}
if (id < (workers.length - 1)) {
synchronized (workers[id + 1]) {
workers[id + 1].notify();
}
}
if (id > 0) {
synchronized (workers[id - 1]) {
workers[id - 1].notify();
}
}
synchronized (this) {
if (workers.length != 1) {
if (id == (workers.length - 1) && workers[id - 1].done) {
continue;
}
if (current > itemCounter) {
done = true;
break;
}
wait();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int workerCounter = 0;
if (args.length != 2) {
System.err.println("Error, use two arguments!");
throw new Error();
} else {
try {
workerCounter = Integer.parseInt(args[0]);
itemCounter = Integer.parseInt(args[1]);
if (workerCounter <= 0 || itemCounter <= 0) {
throw new Exception();
}
} catch (Exception e) {
System.err.println("Error: Invalid args.");
System.exit(1);
}
System.out.println(workerCounter + " Workers; " + itemCounter + " Items");
workers = new Worker[workerCounter];
for (int i = 0; i < workers.length; i++) {
workers[i] = new Worker("Worker" + (i + 1), i);
}
for (int i = 1; i < workers.length; i++) {
workers[i].start();
}
workers[0].start();
}
}
}
Как верно было подмечено выше synchronized (this)
в данном случае не имеет смысла, т.к. лок захватывается на экземпляр Worker
, который вызвал метод run()
. Насколько я понял из задачи, Вам нужно синхронизироваться по полю current
.
Но синхронизации в этом случае стоит предпочесть атомики, т.к. они работают гораздо быстрее. В Вашем случае можно использовать AtomicInteger
и его методы: incrementAndGet(), compareAndSet()
.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Нужно каким то образом при первом запуске создавать БД с рецептами блюд, чтобы затем их просто подгружать из БД и всеКак это можно сделать?...
Существует 7 вариантов опции cascade у HibernateХотелось бы уточнить какого именно поведения ожидать от каждой из них
Заметил такую проблему на андройде 41