5

我正在制作一个程序,其中 x 个线程池与共享库存交互。在这种情况下,我使用 ArrayList 作为共享库存。在我的程序中,线程是生物所拥有的工作的表示。生物属于一个政党,并共享一个用于执行工作的神器池。任何时候只有一个生物与水池互动。

出于某种原因,我一直遇到线程通信问题。我已经设置好了,所以如果池子没有被使用,这个生物会把它所有的物品都扔到池子里并开始查看它。如果他们找不到他们需要的一切,他们应该将他们拥有的所有神器放入池中,将池设置为不忙,然后向一个在池中等待的生物发出信号,表示它也准备好让他们通过它。

我的问题是,如果一个生物在另一个生物等待时正在查看池,并且它无法找到它喜欢的东西,它会重复该过程而不通知或让另一个生物通过它。

我尝试过的:我最初尝试使用锁,但锁不会向其他线程发出信号。然后我利用 synchronized ( Party ) 重写了它。然后我认为这是因为线程在某个地方崩溃了,但是一个线程可以一直运行,甚至在工作完成时将其项目转储回池中(假设一个生物没有将池锁定在边缘)。

boolean ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
    //checks to see if creature already has correct amount of each item.
    //If it does it should skip pool interaction until it dumps its used items
    //back into the pool.
    System.out.println( "Ready: " + ready );
    while ( !ready ) {//begin pool interaction
        synchronized ( target.poolParty ){
            System.out.println( "Ready: " + ready );
            System.out.println( this );
            while ( target.poolParty.busyPool ) {//busyPool is initialized false
                startJob.setEnabled( false );
                try {
                    target.poolParty.wait();
                } catch ( InterruptedException e ) {}
            }
            synchronized ( target.poolParty ) {
                target.poolParty.busyPool = true;
                target.poolParty.notifyAll();//notify all threads that they need to wait because this one will proceed
            }
        }
        target.releaseArtifacts();// adds all artifacts held by creature to an arraylist in poolParty
                                  //then clears the creatures inventory
        target.pickUpArtifacts( reqStones, reqPotions, reqWands, reqWeapons );

        ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
        if ( ready ) {
            synchronized ( target.poolParty ) {
                System.out.println( "has required Items" );
                target.poolParty.busyPool = false;
                target.poolParty.notify();
            }
        } else {
            synchronized ( target.poolParty ) {
                System.out.println( "Does not has required Items" );
                target.poolParty.busyPool = false;
                target.releaseArtifacts();
                target.poolParty.notifyAll();
                try {
                    Thread.sleep( 1000 );
                } catch ( InterruptedException e ){}
            }
        }
    }//end pool interaction

我在一个生物有不止一项工作但一次只能完成一项工作并且工作完美的场景中执行这种线程之间的交互。我定制了这些方法以适应这种情况,但我仍然遇到问题。

注意:我对并发非常陌生,所以如果我的词汇没有在这个主题上发展,请原谅我。

4

2 回答 2

1

看起来你是在思考这个问题。您的用例很简单。

  • 在任何给定时间,只有一个生物应该能够访问池。
  • 在此期间,其他生物必须等待。
  • 这里的共享资源是池。

现在一个简单的

synchronize(pool){
//doStuff
}

应该管用。

请注意,wait()notify()/notifyAll()您需要同步不能很好地落入单个连续逻辑块的代码的不同部分时,需要使用 和。

boolean ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
//checks to see if creature already has correct amount of each item.
//If it does it should skip pool interaction until it dumps its used items
//back into the pool.
System.out.println( "Ready: " + ready );
if ( !ready ) {//begin pool interaction
    synchronized ( target.poolParty ){
        System.out.println( "Ready: " + ready );
        System.out.println( this );
        startJob.setEnabled( false );
    }
    target.releaseArtifacts();// adds all artifacts held by creature to an arraylist in poolParty
                              //then clears the creatures inventory
    target.pickUpArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
    }
}//end pool interaction
于 2013-07-27T12:48:05.057 回答
1

看起来你正在一个target.poolParty用于同步的块中睡觉。这意味着等待访问池的其他线程将无法访问它,因为该线程正在阻塞它。移动到sleep()外面那个方块。

在另一个地方,您synchronized (target.poolParty)在已经使用该块进行同步的块中使用。这是不必要的(好吧,整个代码块是不必要的,我删除了它。只是指出)。也是低级同步原语,很少需要wait()notify*()

boolean ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
//checks to see if creature already has correct amount of each item.
//If it does it should skip pool interaction until it dumps its used items
//back into the pool.
System.out.println( "Ready: " + ready );
while ( !ready ) {
    // begin pool interaction
    synchronized (target.poolParty) {
        target.pickUpArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
        ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );

        /* I'd move this here. If we never release out items then the
           other party members can't use them while this one still does
           not have the needed items. Now they will be available to
           other parties while this thread sleeps. */
        if (!ready) {
            // adds all artifacts held by creature to an arraylist in poolParty
            target.releaseArtifacts();
        }
    }

    // These don't access the pool, so they can be outside the synchronized block
    if ( ready ) {
        System.out.println( "has required Items" );
    } else {
        System.out.println( "Does not have required Items" );
        // Sleep before the next try to get the required items. Lets other
        // threads attempt to fetch their needed items
        try {
            Thread.sleep( 1000 );
        } catch ( InterruptedException e ) {
            // Added, because silently eating exceptions is a bad idea
            e.printStackTrace();
        }
    }
}//end pool interaction
于 2013-07-27T12:38:50.720 回答