2016-07-04 9 views
1

開発中のアンドロイドアプリでは、いくつかの繰り返しタスクを処理するために余分なスレッドを作成する必要があります。私はただ1つのスレッドしか必要とせず、タスクは非常にシンプルですが頻繁に、間欠的で、順番にする必要がありますnewSingleThreadExecutorとwait()とnotify()を使用した新しいスレッド()

私はExecutors.newSingleThreadExecutorがこのような状況に適していると考えました。しかし、私は本当に新しいスレッドを作成する上でこれを使用する利点を得ることはありません。

Executors.newSingleThreadExecutorを使用してsubmit()関数を使用してタスクをキューイングする代わりに、専用のスレッドを作成するのは悪いですか?私はそれがタスクのキューを通過するようにし、キューが空のときに待機し()、メインスレッドが新しいタスクを送信すると、ワーカースレッドに通知します。これは悪い習慣ですか?

// loop for worker thread 
public class WorkerThrd extends Thread { 

    public void run() { 
     while(true){ 

      while (!queue.empty()) { 
       queue.getTask().doSth(); 
      } 
      synchronized(this){ 
       try { 
        wait(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

// from main thread 

private WorkerThread wthread; 
public void initiation(){ 
    wthread = new WorkerThread(); 
    wthread.start(); 
} 

public void postSth(){ 
    wthread.queue.post(new task()); // a thread safety queue 
    synchronized(wthread){ 
     if(wthread.getState() == Thread.State.WAITING) { 
      wthread.notify(); 
     } 
    } 
} 

P.S.待ち行列がスレッドセーフであると仮定していましたが、wait()またはnotify()を呼び出すたびに同期ブロックが必要ですか? 1つのスレッドだけがwait()を呼び出し、他の1つのスレッドがnotify()を呼び出す場合でも、

+0

状態を確認したときにスレッドが待機していない場合はどうなりますか?どのようにこれまでに通知されますか? –

+2

ホイールを改造することは**悪い習慣です、はい。また、あなたの実装は 'doSth()'でスローされた例外を処理しません... – Fildor

+0

@Andy Turnerそれがループになるので、待機していないときに通知する必要はありません。 –

答えて

2

利点は次のとおりです。ホイールを再発明していないことです。

真剣に:あなたの単純なワーカースレッドが今日仕事をしているかもしれません。しかし、チャンスは、遅かれ早かれそうです。物事はより複雑になるでしょう。その意味では、「プログラミング」は常に「変化のために開いている」と「それは必要ではない」とのバランスをとっています。

Executorsフレームワークの素晴らしい点は、きれいで分かりやすい抽象レイヤーを提供することです。あなたが気にしているのは、タスクを提出することだけです。

あなたは知っています:そのような抽象化によって、例えばスレッドごとに起こっていることを心配することなくユニットテストを書くなど、多くのことが可能になります。実際にcurrent threadで使用するエグゼキュータを使用してください。そして、これまでに「マルチスレッド」コードの単体テストを書いた人はどれほど難しいかを知っています。

+0

車輪を発明し直して一つのことを達成する。スレッドがいくつかの状態情報を保持していて、newSingleThreadExecutorがスレッドをランダムに破棄して再作成できると聞きました。私はこの問題を解決するためにいくつかの方法を考え出しているだけです。 –

+0

あなたはあなたの質問にその要件を言及していたはずです。はい、あなたは正しいです、そのサービスは、必要に応じて新しいスレッドを作成するかもしれません。しかし、重要な点は、基底のスレッドが「病気」になった場合にのみ実行されることです。あなた自身が "スレッドが病気である"と "そのために必要なアクション"を検出するコードをすべて記述しようとしていますか? – GhostCat

+0

タスク間で状態を共有する必要がある場合は、共有状態を保持するクラスを用意し、作成時にそれぞれのタスクに同じインスタンスを渡します。これは "生の"スレッドの使用を必要としません。 –

1

newSingleThreadExecutorは、コードが予期しているときは特別なタイプのExecutorServiceとしてかなり役に立ちます。それは専用のThreadよりわずかな利点があります。唯一の違いは、独自のキュー、同期などを実装してホイールを再開発する必要がないことです。最高のパフォーマンスを達成するために低レベルの同期パターンを使用するように最適化されていますので、同様の機能が期待される場合は既存のものを使用することをお勧めします。

また、あなたが提供されたコードは非常に間違っています:

  1. wait()notify()両方の周りの同期が欠落して労働者
  2. のないインスタンス化。
  3. wait()およびnotify()は、BlockingQueueの実装がすでに待機機能を提供しているので、ここでは完全に不要です。
+0

ええ、私はそれを修正しなければならないいくつかの部分を省略しました。そして、2番目は私の最後の質問の一部ですが、3番目の部分は指摘しました。私はちょっと興味があります。キューが空であってもループが刻々と変化します。 –

関連する問題