0

pauseThread() を呼び出すたびに、常に IllegalMonitorStateException がスローされます。

ドキュメントで、スレッドを待機させるには、オブジェクト モニターを所有する必要があることに気付きました。

このコードで

synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condition
     }

この場合、obj パラメータは while(ServerTickHandler.peakBlockDestructionQueue() == null){} のランナーになりますが、obj.wait(); 通知する必要がありますか?または、while 条件が true でない場合に自身に通知しますか? 同期された (){} コード ブロックは継続的にループしますか、それとも同期された (){} 内でこれを達成するために while ループが必要でしょうか?

編集: syncronized(){} は run メソッドによって内部に入りますか?

ここに私のクラスがあります

public class ServerTickSaveHandler implements Runnable
{
    private static Thread   runner;
    /**
     * Creates a new thread for dealing with logging block destruction when using certain tools.
     * @param threadName Name of the thread.
     */
    public ServerTickSaveHandler(String threadName)
    {
        runner = new Thread(this, threadName);
    }
    /**
     * If thread has nothing to do we shall pause it so it does not needlessly run :D.
     * @throws InterruptedException
     */
    public void pauseThread()
    {
        try
        {
            runner.wait();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        catch(IllegalMonitorStateException e)
        {
            e.printStackTrace();
        }
    }
    /**
     * If Items from DropItemQueue need ticking lets resume this thread.
     * @throws IllegalMonitorStateException
     */
    public void resumeThread()
    {
        try
        {
            runner.notify();
        }
        catch (IllegalMonitorStateException e)
        {
            e.printStackTrace();
        }
    }
    /**
     * The thread that is spawned when this object is created.
     */
    public void run()
    {
        while (true)
        {
            // long start = System.currentTimeMillis();

            WorldData worldData = ServerTickHandler.getBlockDestructionQueue();
            if (worldData != null)
            {
                worldData.saveToFile();
            }
            else pauseThread();

            // long end = System.currentTimeMillis();

            // NumberFormat formatter = new DecimalFormat("#0.00000");
            // Utils.log("Save Tick Handler Execution time is " +
            // formatter.format((end - start) / 1000d) + " seconds");
        }
    }
    /**
     * Starts the thread.
     * @throws IllegalStateException
     */
    public void startThread()
    {
        try
        {
            runner.start();
        }
        catch (IllegalStateException e)
        {
            e.printStackTrace();
        }   
    }
}
4

1 に答える 1

2

wait()文書化されているように、 /を呼び出すオブジェクトのモニターを保持する必要がありますnotify()。これらのメソッドをで呼び出しているのでrunner、これらの命令は内部にある必要があります

synchronized(runner) {

ブロック。

とはいえ、スレッドでwait()/を呼び出すのは非常に奇妙な選択です。notify()待機/通知には、最後の専用ロックオブジェクトを使用することをお勧めします。あなたのプログラムには他にも悪い選択があります。たとえば、コンストラクターから静的フィールドを初期化します。

wait()非常にnotify()低レベルで、使用しにくいプリミティブです。代わりに、ロック、セマフォ、CountDownLatches、BlockingQueuesなどの高レベルの抽象化を使用する必要があります。

于 2013-03-20T22:22:52.947 に答える