美好的一天!
我遇到了在 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/