java - Java中唤醒线程的问题

原文 标签 java multithreading

再会!

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

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

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

最佳答案

您正在wait()对象上调用notifyAll()Thread。那不是做事的方式-您在所有相关线程都拥有的某个通用对象上调用它。

在每种情况下,您只在当前线程上进行同步也是没有意义的,因为没有其他东西可以在该线程上进行同步,因此同步是没有意义的。

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

(我也建议您不要调用Thread.interrupt-目前尚不清楚您为什么在这里这么做...)

编辑:如注释中所述,请查看java.util.concurrent中的更高层次的抽象,例如 Semaphore ,以实现目标的可能更简单的方法。

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

相关文章:

Java 和 UseLargePages

java - 信任库是否也需要 CA 的证书来进行身份验证?

java - 未调用方法doOnComplete,doOnTerminate或doOnError

ios 两种方式自定义委托(delegate)

java - 在android中从并行线程中的大量文本文件中加载数据

java - 共享变量的陈旧值

java - 如何使用命令行命令重新启动Glassfish

java - "EEEE, MMMM d, yyyy ' 在 ' HH:mm"

multithreading - Perl:让线程进入休眠状态

java - 如何在Android中使用intentservice同时下载多个文件?