質問: queue.poll(2, TimeUnit.SECONDS); System.out.println("poll() : " + pNum); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } ### 実行結果 offer(): 1 offer(): 2 offer(): 3 poll(): 0.24829714919143642 poll(): 0.9951008257327133 offer(): 3 poll(): 0.2502551360660312 poll(): 0.931467810599396 poll(): 0.08339082618949567 offer(): 2 <続く>
回答: Thread and/or LinkedBlockingQueueの機能について勘違いされていると思います。 Threadというのは「ブロックされていない限り勝手に先にすすむもの」です。勝手に先にすすむというのは曖昧な言い方ですが、少し細かく言えば「OSによってプロセッサが割り当てられればいつでも処理は進む」とでもいいましょうか。通常OSにはPCに搭載されたプロセッサ(例えば2コアなら4プロセッサ)の数よりずっと多いスレッドが動いていますのでOSがいつどのスレッドにプロセッサを割り当てるかはその時々の状況次第なのでどのスレッドがいつ動くかの厳密な予測はできないと思ってください。 ただし最初にいったとおり「ブロックされていれば絶対に先には進みません」そういうときはOSが「このスレッドは先に進めないのだからプロセッサを割り当てても無駄」と判断して別の(ブロックされていない)スレッドにプロセッサを割り当ててしまいます。 このプログラムでいえばスレッドのブロックはLinkedBlockingQueueに対する操作で発生します。その発生条件は以下のようなものです。 * offerしようとしたが、キューがいっぱいのためそれ以上offerできない場合 * pollしようとしたが、キューが空のために取り出せない場合 以上を考えればoffer側で「3つoffserされてから」poll側のスレッドが動き出して「3つpollされる」といったような動きにはならないということがわかると思います。offer側が最初の要素をofferしたとたんにpoll側スレッドのブロック状態は解除され「いつでも動ける状態」になりますのでOSがプロセッサを割り当てた瞬間に動き出します。 整理すると以下のようになりますので、キューの要素数が1,2であればoffer, pollどちらのスレッドが先に動くかは状況次第になります。 * offer側のスレッド キューの要素数が3でない限りいつでも動けます * poll側のスレッド キューの要素数が0でない限りいつでも動けます > > 実行結果の4,5行目でpollで要素を2つ削除しているのに6行目でofferのあと、要素数が3 > > > **以下の回答は回答者の勘違いでした: 失礼しました** 単に勘違いされているだけでしょうが、要素が2の状態でofferが動くときのご自分のコードをご覧ください。要素を追加した後でキューのサイズを印字していますね?ゆえに要素数が2のときにofferが動けば印字結果が3になることに不思議はないはずです。 訂正した回答: デバッグプリントもスレッド上で動いている処理の一つですのでどのような順序で動くかは状況次第であることに注意すると何が起こっているかが推測できると思います。例えば以下の順序で動いたとするとご質問にある結果になり得ると思います。 * 要素数3の状態でpollが実行され要素数が3->2に変わった(A) * (A)のデバッグプリントが印字された * 要素数2の状態でofferが実行され要素数が2->3に変わった(B) * 要素数3の状態でpollが実行され要素数が3->2に変わった(C) * (C)のデバッグプリントが(先に)印字された * (B)のデバッグプリントが(ようやくここで)印字された