Увеличение переменной с помощью 3 потоков, которые переключаются по очереди

Мне нужно перебрать int от 0 до 100 с 3 потоками. Так чтобы переменная передавалась из потока в поток. Я сделал так, чтобы было всего 2 потока Consumer и Producer. Но нужно чтобы каждый из трех потоков был и Consumer и Producer одновременно и передавать переменную по кругу пока int не станет 100.

A -> i++ -> send B -> B accepts -> i++ -> send C -> C accepts -> i++ -> send A -> A accepts -> i++

Заранее спасибо за вашу поддержку!

public class TransferQueueExample {

TransferQueue<String> queue = new LinkedTransferQueue<String>();

class Producer implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i <= 100; i++){
            try{
                System.out.println("Producer waiting to transfer: " + i);
                queue.transfer("" + i);
                System.out.println("Producer transferred: " + i);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i <= 100; i++){
            try{
                System.out.println("Consumer waiting to consume: " + i);
                queue.take();
                System.out.println("Consumer consumed: " + i);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

public static void main(String args[]){
    TransferQueueExample example = new TransferQueueExample();
    new Thread(example.new Producer()).start();
    new Thread(example.new Consumer()).start();
}

}

Ответы (1 шт):

Автор решения: Alexey R.

Можно сделать так:

  1. Создаем класс объект которого будем шарить:
public class SharedState{

    volatile int i = 0;
    boolean stop = false;

    @Override
    public String toString() {
        return "SharedState{" +
                "i=" + i +
                ", stop=" + stop +
                '}';
    }
}
  1. Создаем класс потока. В этот поток будет входить одна очередь, а исходить из него другая:
public class Incrementer implements Runnable{

    BlockingQueue<SharedState> incomingQueue;
    BlockingQueue<SharedState> outcomingQueue;

    public Incrementer(BlockingQueue<SharedState> incomingQueue,
                       BlockingQueue<SharedState> outcomingQueue){
        this.incomingQueue = incomingQueue;
        this.outcomingQueue = outcomingQueue;
    }

    @Override
    public void run() {
        while(true){
            try {
                SharedState state = incomingQueue.take();
                System.out.println(Thread.currentThread().getName() + " took " + state);
                if(state.stop){
                    outcomingQueue.put(state);
                    break;
                }else if (state.i != 100){
                    state.i++;

                }else{
                    state.stop = true;
                }
                System.out.println(Thread.currentThread().getName() + " sent " + state);
                outcomingQueue.put(state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
  1. Запускаем всё, связывая потоки очередями заколльзованно:
public class Main{

    public static void main(String[] args) throws InterruptedException {
        new Main().starter();
    }

    public void starter() throws InterruptedException {
        SharedState sharedState = new SharedState();
        BlockingQueue<SharedState> t1t2 = new LinkedTransferQueue<>();
        BlockingQueue<SharedState> t2t3 = new LinkedTransferQueue<>();
        BlockingQueue<SharedState> t3t1 = new LinkedTransferQueue<>();
        t1t2.put(sharedState);
        new Thread(new Incrementer(t3t1, t1t2)).start();
        new Thread(new Incrementer(t1t2, t2t3)).start();
        new Thread(new Incrementer(t2t3, t3t1)).start();
    }

}
→ Ссылка