简体   繁体   English

线程没有通信

[英]Threads not communicating

I am making a program in which a pool of x number of threads interacts with a shared inventory. 我正在制作一个程序,其中x个线程池与共享库存交互。 In this case I use an ArrayList as the shared inventory. 在这种情况下,我使用ArrayList作为共享库存。 In my program the threads are representations of jobs that a creature has. 在我的程序中,线程是生物具有的作业的表示。 Creatures belong to a party and share a pool of Artifacts used to perform jobs. 生物属于一方并共享用于执行工作的工件池。 only one creature my interact with the pool at any time. 只有一个生物我随时与游泳池互动。

For some reason I keep having issues with thread communication. 出于某种原因,我一直遇到线程通信问题。 I have set it up so if the pool is not being used the creature drops all its items into the pool and begins to look through it. 我已经设置了它,所以如果没有使用游泳池,该生物会将所有物品放入游泳池并开始查看它。 And if they cannot find everything they need they should drop all the artifacts they have into the pool, Set the pool to to not busy, then signal one creature waiting on the pool that it is ready for them to go through it as well. 如果他们找不到他们需要的所有东西,他们应该将他们拥有的所有工件放入池中,将池设置为不忙,然后发信号通知一个等待池的生物,它已准备好让它们通过它。

My issue is that if a creature is looking through the pool while another is waiting, and it cannot find what it like it repeats the process without notifying or letting the other creature go through it. 我的问题是,如果一个生物正在通过水池观察而另一个正在等待,并且它无法找到它想要的东西,它会重复该过程而不会通知或让其他生物通过它。

What I've attempted: I initially attempted using locks but the locks would not signal other threads. 我尝试过的:我最初尝试使用锁,但锁不会发出其他线程的信号。 Then I rewrote it taking advantage of synchronized ( Party ). 然后我利用synchronized(Party)重写了它。 Then I thought it was because the threads were crashing somewhere but a thread can run all the way through and even dump its items back into the pool when the job is complete (given a creature has not locked the pool into limbo). 然后我认为这是因为线程在某个地方崩溃,但线程可以一直运行,甚至在作业完成时将其项目转回到池中(假设生物没有将池锁定到空中)。

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

I perform this kind of interaction between threads in a scenario where a creature has more than one job but can only do one job at a time and it works perfectly. 我在线程中执行这种交互,在一个场景中,一个生物有一个以上的工作,但一次只能做一个工作而且它完美地工作。 I tailored those methods to match this situation and I am still having issues. 我根据这种情况量身定制了这些方法,但我仍然遇到问题。

Note: I'm very new to concurrency so forgive me if my vocabulary is not as developed on the subject. 注意:我对并发很新,所以请原谅我,如果我的词汇不是在这个主题上发展的话。

It looks like you are sleeping in a block that uses target.poolParty for synchronization. 看起来你正在使用target.poolParty进行同步的块中睡觉。 That means that the other threads waiting to access the pool won't be able to access it because this thread is blocking it. 这意味着等待访问池的其他线程将无法访问它,因为该线程正在阻止它。 Move the sleep() outside that block. sleep()移到该块之外。

At another place you use synchronized (target.poolParty) in a block that already uses that for synchronization. 在另一个地方,您在已经使用synchronized进行同步的块中使用synchronized (target.poolParty) That is unnecessary (well, the whole block of code is unnecessary and I removed it. Just pointing out). 这是不必要的(好吧,整个代码块是不必要的,我删除它。只是指出)。 Also wait() and notify*() are low level synchronization primitives and rarely needed. 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

Looks like you are over thinking the problem. 看起来你在想这个问题。 Your use case is simple. 您的用例很简单。

  • Only one creature should be able to access the pool at any given time. 在任何给定时间,只有一个生物应该能够访问该池。
  • Other creatures must wait during that time. 其他生物必须在此期间等待。
  • Shared resource here is the pool. 这里的共享资源是池。

Now a simple 现在很简单

synchronize(pool){
//doStuff
}

should work. 应该管用。

Note that wait() and notify()/notifyAll() are needed when you need to synchronize different portions of code which don't nicely fall into a single consecutive logic block. 请注意,当您需要同步不完全属于单个连续逻辑块的不同代码部分时,需要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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM