How do I get an object from BlockingQueue?

I have a class X

, class Machine

, class Z

, all of them are Threads. When streams are initialized Machine

, they are placed in BlockingQueue firstQueue

. The run method inside the machine has a while loop that checks if its boolean variable should be true or false. When this is true, the car should be put onBlockingQueue secondQueue

secondQueue.put(this);

      

and the Z

class can take it from there. If the machine thread returns false, the class X

can take the machine from firstQueue

and work with it. Now, my question is, when boolean is true, is it possible to make Machine

from firstQueue

? PS: I know the question might be vaguely asked, but I don't know how to shape it correctly. If anyone knows how to make it better, please fix it.

EDIT. Sample code. Here is a part from the class that starts all threads, all queues are initialized of course.

public class Machine implements Runnable{
private final BlockingQueue firstQueue;
private final BlockingQueue secondQueue;
boolean broken;

public Machine(...){...}


 public void run() {

    while(true){
            //use Rand (min=0, max=1) and define if(random==1)broken=true else broken=false

            if(broken==true){
                Machine multi = fistQueue.take(this);//here is problem!!!!!
                secondQueue.put(this);
            }  
     }
}...}

      

and the part shape class that starts the threads

//machines should have an ability to take themselves from queue when broken==true, and then put on secondQueue
BlockingQueue<Machine> firstQueue = new ArrayBlockingQueue<Machine>(10);
    service=Executors.newFixedThreadPool(10);
    for(int k=0; k < 10; k++){
        Machine M= new Machine(secondQueue, k);
        firstQueue.add(M);
        service.submit(M);
    }

 //X can take machines from firstQueue, and work on them if broken==false
Thread XThread = new Thread(new X(firstQueue));
    XThread.start();

//takes machines form secondQueue
    Thread ZThread = new Thread(new Z(secondQueue));
    ZThread.start();

      

EDIT2

public class X implements Runnable(){

//fields, constructor

public void run() {

    while(true){
            machine=machines.take();
            if(machine.broken==true){
                //leave this machine (it should be on , and take other which is fine_
            } 
            while(machine.broken==false){
                machine.pass(record); // (Record record=new Record(task, result field);
               //do Your thing
           }
           if(result==initialResultFromX){
              //means it got broken while working and needs to take a new machine
             }
}...
}

      

+3


source to share


1 answer


First, this answer aims to help improve the design of the solution, which in turn might answer the real question. However, if the OP is happy with the current construct, I believe this question can be answered by removing the following line:

Machine multi = fistQueue.take(this);

      

So,

Is it possible to force the machine to pick itself up from firstQueue?

There is no way to directly get the object inside the queue without deleting it (as pointed out in the comments, the machine should not be removed from the first queue). Since you can access the machine instance using this

, secondQueue.put(this)

it would be sufficient to add Machine

in the second queue.

I might misinterpret your design, but it seems to me that everyone Machine

has a state. This state depends on whether or not he can Machine

do what he has to do. If so, I think it is not wise to keep the handling of state changes in the machine itself (adding / removing itself to different run queues).

You need an abstraction. Lets call it yours StateMachine

. StateMachine

creates, manages and handles changes to the state of each Machine

, implementing some kind of listening interface. This will allow each machine to report any events or problems to the StateMachine

. It StateMachine

can then determine how to handle the events.

I will try to explain with an example. Here is the interface that implements StateMachine

:

public interface BrokenListener {
    public void onBrokenEvent(Object machine);
}

      

This allows communication between StateMachine

and everyone Machine

. However, this requires that an instance StateMachine

be passed to each machine instead of queues.



for(int k=0; k < 10; k++){
    Machine m = new Machine(this); //where this is the StateMachine
    firstQueue.add(m);
}

      

As soon as the state Machines

changes from broken == false

to broken == true

, you can call onBrokenEvent()

.

public class Machine {
    /* The listener */
    private BrokenListener listener;
    private boolean broken = false;

    public Machine(BrokenListener listener) {
        this.listener = listener;
    }

    /* When the state of the machine changes */
    public void setBroken(boolean broken) {
        this.broken = broken;
        if (this.broken) {
            //Here we pass the current Machine to the StateMachine. How the event is handled should not be up to the machine.
            this.listener.onBrokenEvent(this);                
        }
    }
}

      

Here is StateMachine

:

public class StateMachine implements BrokenListener {
    @Override
    public void onBrokenEvent(Object machine) {
        if (machine instanceof Machine) {
            second.add((Machine) machine);
        }
    }
}

      

As you can see when the state apparatus implements the method onBrokenEvent

. When this method is called Machine

, it can be added to a second queue for processing.

I assume that the classes are X

and Y

will handle, so you still need to pass queues to them.

Thread XThread = new Thread(new X(firstQueue));
XThread.start();

Thread ZThread = new Thread(new Z(secondQueue));
ZThread.start();

      

What makes it nice is it retains the logic used to handle state changes from Machine

.

Feel free to ask any questions.

+1


source







All Articles