在java中唤醒线程的问题

时间:2011-04-15 16:44:55

标签: java multithreading

美好的一天!

我遇到了在Java中同步线程的问题。

我有3个进程(我将它们保存在ConcurrentHashMap< Integer,Integer> man)和4个资源(我将它们保存在ConcurrentHashMap< Integer,Integer>资源中)。

每个进程只能容纳2个直接资源。例如,man [0]只能保存资源[0]和资源[1],man [1]只能保存资源[1]和资源[2]等。

所以我几乎没有什么情况下线程必须等到其他线程不会释放他们的资源。所以这个线程会等待...当我调用notifyAll()时它不会唤醒!

我的逻辑出了什么问题?

这是我的代码:

import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Philos
{
    private Thread thisThread;

public Philos()
{
    for ( int i = 1; i <= 4; i++ )                                          //Init processeses and resourses.
    {
        resourses.put( i, 0 );                                              //Each is free.
        man.put(i, 0);
    }
}


public void startThread( final int i )
{
    thisThread = new Thread()
    {
         public void run()
         {

             try {
                System.out.println(Thread.currentThread().getName());
                Eat( i );                                                   //Proc try to start work
                show( i, "Eat" );                                           //Show res and procs

                finishEat( i );                                             //Release resourses.
                show( i, "Release" );
                thisThread.interrupt();                                     //Finish threads
            } catch (InterruptedException ex) {
                Logger.getLogger(Philos.class.getName()).log(Level.SEVERE, null, ex);
            }
         }


    };

    thisThread.start();

}


private synchronized  void Eat( int i ) throws InterruptedException
    {
        testEat ( i );                                                          //Try to work.
        if ( !( man.get(i) == 1 ) )                                             //If proc are not working
        {
            System.out.printf("%d must wait\n", i);
            synchronized( Thread.currentThread() )                              //Put synchronize block to wait thread
            {
               Thread.currentThread().wait();                                   //Thread must wait
               System.out.println("Notifyied");
            }
        }

    }

private synchronized  void finishEat( int i ) throws InterruptedException
{
            man.put( i, 0 );                                                        //Release proc
            resourses.put(i,   0);                                                  //Release resourses of proc
            resourses.put(i+1, 0);
}


private synchronized  void testEat( int i ) throws InterruptedException
{
        System.out.printf("Test %d\n",i);
        if ( ( left(i) == 0 ) && ( right(i) == 0 ) )                            //If resourses availible
        {
            man.put( i, 1 );                                                    //Proc is busy
            resourses.put(i,   1);                                              //Resourses are busy
            resourses.put(i+1, 1);

            synchronized( Thread.currentThread() )
            {
                Thread.currentThread().notifyAll();                             //Notify al threads
            }
        }
}


private int left( int i )                                                   //Check left resourse.
    {
        return (resourses.get(i));
    }

    private int right( int i )                                                  //Check right resourse.
    {
        return (resourses.get(i+1));
    }

    private synchronized  void show( int i, String info )                       //Show info about resourses and proc
    {
        System.out.printf("\nid = %d, [%s]\n", i, info );

        System.out.println("Work[R]:");
        for ( int j = 1; j <= 4; j++ )                                          //Res
        {
            System.out.printf( "%d ", resourses.get(j) );
        }
        System.out.println();
        for ( int j = 1; j <= 4; j++ )                                          //Proc
        {
            System.out.printf( " %d", man.get(j) );
        }
        System.out.println();
    }


    private ConcurrentHashMap< Integer, Integer > resourses = new ConcurrentHashMap< Integer, Integer >();
    private ConcurrentHashMap< Integer, Integer > man = new ConcurrentHashMap< Integer, Integer >();
}

1 个答案:

答案 0 :(得分:2)

您在wait()对象上呼叫notifyAll()Thread。这不是做事的方式 - 你把它称为所有相关线程所持有的一些共同对象。

在每种情况下,你只对当前线程进行同步这一事实也没有意义 - 在该线程上没有其他任何东西可以同步,因此同步毫无意义。

您需要确定要同步/等待/通知的公共对象。通常我更喜欢仅为此目的创建单独的对象,但您也可以重用现有对象。

(我还建议你不要致电Thread.interrupt - 我不清楚你为什么要这样做......)

编辑:正如评论中所提到的,请查看java.util.concurrent中的更高级抽象,例如Semaphore,以便更简单地实现目标。