Java 如何从BlockingQueue中获取对象?

Java 如何从BlockingQueue中获取对象?,java,multithreading,Java,Multithreading,我有一个classX,classMachine,classZ,它们都是线程。当机器线程被初始化时,它们被放在阻塞队列firstQueue上。在机器的run方法中有一个while循环,用于检查其布尔变量是true还是false。如果为真,则应将机器置于BlockingQueue secondQueue secondQueue.put(this); 而Z类可以从那里获得它。若机器线程返回false,则类X可以从firstQueue获取机器并处理它。 现在,我的问题是:当布尔值为真时,是否有可能使机

我有一个class
X
,class
Machine
,class
Z
,它们都是线程。当
机器
线程被初始化时,它们被放在
阻塞队列firstQueue
上。在机器的run方法中有一个while循环,用于检查其布尔变量是true还是false。如果为真,则应将机器置于
BlockingQueue secondQueue

secondQueue.put(this);
Z
类可以从那里获得它。若机器线程返回false,则类
X
可以从
firstQueue
获取机器并处理它。 现在,我的问题是:当布尔值为真时,是否有可能使
机器
firstQueue
获取自身? 另外,我知道这个问题可能被问得不清楚,但我不知道如何恰当地表达出来。如果有人知道如何改进,请更正

编辑。 代码示例。 这是类的一部分,它启动所有线程,当然初始化所有队列

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);
            }  
     }
}...}
以及启动线程的部分表单类

//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();

首先,此答案旨在帮助改进解决方案的设计,从而回答实际问题。但是,如果OP对当前的设计感到满意,我相信可以通过删除以下行来回答这个问题:

Machine multi = fistQueue.take(this);
所以

有没有可能让机器从第一个队列中自动起飞

没有方法可以在不删除对象的情况下直接获取队列中的对象(如注释中所述,不应从第一个队列中删除机器)。因为您可以使用
this
访问机器的实例,
secondQueue.put(this)
机器添加到第二个队列就足够了

我可能误解了您的设计,但在我看来,每台
机器都有一个状态。此状态取决于
机器
是否能够执行它必须执行的任何操作。如果这是真的,我认为在机器本身中保持状态更改的处理(将自身添加/删除到不同的执行队列)是不明智的

你需要某种抽象。让我们将其称为您的
状态机
StateMachine
通过实现一些侦听接口来创建、管理和处理每个
机器的状态更改。这将允许每台机器向状态机报告任何事件或问题。然后,状态机可以确定如何处理事件

我将试着举例说明。以下是
状态机
将实现的接口:

public interface BrokenListener {
    public void onBrokenEvent(Object machine);
}
这允许
状态机
和每个
机器
之间进行通信。但是,这需要将
StateMachine
的实例传递给每台机器,而不是队列

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

public class StateMachine implements BrokenListener {
    @Override
    public void onBrokenEvent(Object machine) {
        if (machine instanceof Machine) {
            second.add((Machine) machine);
        }
    }
}
如您所见,当状态机实现
onbrokenvent
方法时。当
机器调用此方法时,可以将其添加到第二个队列中进行处理

我假设
X
Y
类将进行处理,因此您仍然需要将队列传递给它们

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

Thread ZThread = new Thread(new Z(secondQueue));
ZThread.start();
这样做的好处是,它将用于处理状态更改的逻辑保留在
机器之外


请随意提问。

如果您放入相关代码,会更容易。为什么您不能先检查布尔值的状态,然后将机器对象放入适当的队列?原则上是的,因为类
BlockingQueue
有一个
移除(对象o)
方法,可以从队列中移除对象,无论对象在队列中的什么位置。这个设计是否是个好主意是另一个问题。在我看来,你是在不必要地使事情复杂化。您可以使用Executor服务(FixedPool)并解决此问题。使用executor服务的优点是不需要公开阻塞队列实现。如果你想得到准确的答案,请提供示例代码。@Jesper我不能删除它们,它们必须在那里。非常感谢你的回答。我知道这可能是一个noob问题,但可以解释一下为什么在方法setBroken中使用这样的语法:
this.break=break
?我假设变量
break
有一个setter方法。在您的示例中,
boolean
变量
breaked
如何从未初始化更改为
true
?我还编辑了我答案的第一部分,它随机变化。我有一个给我随机数的方法,然后在运行中我签入,如果这个数等于我选择用来表示“如果机器坏了”的数字,如果是的话,那么它会将坏掉的变量设置为true,所有关于队列的魔法,现在应该出现监听器。编译后没有错误,但即使有可能,机器也不会崩溃。此声明是否有问题:在类中,在for循环
静态状态机状态中启动线程,然后在main
状态中=新状态机(第二)
Machine M=newMachine(state,k,listener,second)
我知道您告诉我不要将队列放入新机器中,但是如果没有它,我如何调用
StateMachine
inside
Machine
?因此run方法不仅检查机器,而且确定机器是否损坏?您需要做的是在机器被分类为损坏后立即调用
this.listener.onbrokenvent(this)
<代码>此
引用计算机的当前实例。因此,当调用
onbrokenvent(this)
时,通过传递
this
StateMachine
知道哪个
Machine
被破坏。您应该将
StateMachine
作为侦听器传递,例如
BrokenListener listener=newstatemachine(第一,第二)
newmachine(k,listener)
public class StateMachine implements BrokenListener {
    @Override
    public void onBrokenEvent(Object machine) {
        if (machine instanceof Machine) {
            second.add((Machine) machine);
        }
    }
}
Thread XThread = new Thread(new X(firstQueue));
XThread.start();

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