再会!
我遇到了在Java中同步线程的问题。
我有3个进程(将它们保存在ConcurrentHashMap
每个进程只能容纳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/