2017-05-16 26 views
0

私はnotify()とwait()を使用しようとしています。ここに私の希望するクラスがあります。 addNewItem()に電話するときに問題があります。最初にtryToReadItem()と呼び出してからaddNewItem()メソッドを呼び出すと、そのログは出力されません。私のDemoClassがシングルトンであることに注意してください。ここでAndroidのnotify()メソッドが呼び出されていません

public class DemoClass { 

private static final String TAG = "DemoClass"; 

private static DemoClass instance; 
private Object lock = new Object(); 
private static Thread executor; 
private static Runnable reader; 
static MyQueue queue; 


private DemoClass() { 
    queue = MyQueue.getInstance(); 
    reader = new Runnable() { 

     @Override 
     public void run() { 
      tryToReadRequest(); 
     } 
    }; 

} 

public static DemoClass getInstance() { 
    if (null == instance) { 
     instance = new RequestExecutor(); 
     executor = new Thread(reader); 
     executor.run(); 
    } 
    return instance; 
} 

public boolean addNewItem() { 
    synchronized (lock) { 
     lock.notify(); // executor will be run 
     Log.i(TAG, "executor run..."); 
    } 
    return true; 
} 

public void tryToReadItem() { 

    try { 
     while (true) { 
      synchronized (lock) { 
       if (queue.checkTopValue() == null) { 
        Log.v(TAG, "queue is empty"); 
        lock.wait(); 
       } else { 
        //TODO other code... 
       } 

      } 
     } 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
} 

は、そのクラスの使い方です:

DemoClass executor = DemoClass.getInstance(); 
boolean bool = executor.addNewItem(); 

私は何かが足りないのですか?

編集:私のコードを変更しました。今すぐtryToReadRequest()はキューが空でない間、連続的に実行されます。私の問題は、lock.notify();行が実行されないということです。

+0

これはすべて同じスレッド内にあります。他のスレッドが関わっているはずです。 – Enzokie

+0

通知を変更してnotifyAllに変更した場合、同じ結果を得ていると思いますか? – DEADMC

+0

あなたの問題には関係しませんが、適切なシングルトンのためには、getInstance()とe.printStackTrace()でsynchronizedブロックが必要です。あなたはLogE( "tag"、Log.getStackTraceString(e))を代わりに書く必要があります。 – DEADMC

答えて

0

すべて

 if (queue.checkTopValue() == null) { 
      Log.v(TAG, "queue is empty"); 
      lock.wait(); 
     } 

まずofficial documentation

注意に依存し、このコードには多くの問題があります:常に条件 ためのテストが待機中というループ内での待機を呼び出しますために。あなたが待っていた特定の状態のために割り込みがあったか、または が依然として真であると仮定しないでください。

DemoClassSingletonです。しかしSingleton

安全ではないスレッドが複数のスレッドがnullを渡すことができるので、==

if (null == instance) { 
     instance = new RequestExecutor(); 
     executor = new Thread(reader); 
     executor.run(); 
    } 

正しい方法は、追加の同期ブロック内のチェックや揮発性のインスタンスを使用している同じ時にインスタンス状態。

ので、インスタンスに

private static volatile DemoClass instance; 

を揮発追加し、この

public static DemoClass getInstance() { 
    DemoClass localInstance = instance; 

    if (localInstance == null) { 
     synchronized (DemoClass.class) { 
      localInstance = instance; 
      if (localInstance == null) { 
       localInstance = new DemoClass(); 
       instance = localInstance; 
       executor = new Thread(reader); 
       executor.run(); 
      } 
     } 
    } 
    return localInstance; 
} 

ノートのようなものにするgetInstance()メソッドを書き換え、あなたがsynchronizedブロック内でのみチェックを残すことができますが、それはgetInstanceメソッドを行います遅すぎる。

関連する問題