java - Java中唤醒线程的问题

标签 java multithreading

美好的一天!

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

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

每个进程只能持有 2 个即时资源。例如man[0]只能容纳resources[0]和resources[1],man[1]只能容纳resources[1]和resources[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 >();
}

最佳答案

您正在 Thread 对象上调用 wait()notifyAll()。这不是做事的方式 - 你在所有相关线程持有的一些公共(public)对象上调用它。

在每种情况下,您仅在当前线程上同步这一事实也毫无意义 - 没有其他任何东西会在该线程上同步,因此同步毫无意义。

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

(我还建议您不要调用 Thread.interrupt - 我不清楚您为什么要在这里这样做...)

编辑:如评论中所述,查看 java.util.concurrent 中的高级抽象,例如 Semaphore ,以寻求一种可能更简单的方式来实现您的目标。

关于java - Java中唤醒线程的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5679860/

相关文章:

linux - 用户线程和内核线程与线程级库和内核级库是否有以下任何一种对应关系?

java - 如何从java创建xml文件

c++ - std::packaged_task 是如何工作的

java - 如何读取/更新存储在 map 内的值,该 map 随后位于 Cloud Firestore 的数组内?

java - 同时运行动画和图像切换器

python - 关于Python中线程的困惑

java - spring 集成超时客户端

c++ - 在 Windows 上的 C++ 中使用和创建 wxwidgets 中的线程

java - 这是我直接在 Android 中录制视频的代码,但它不起作用。它只显示黑色屏幕。有人可以帮我吗?

java - Ubuntu 上的外观问题