天天看點

Java多線程與并發庫進階應用-可阻塞的隊列

ArrayBlockQueue 可阻塞的隊列

  > 隊列包含固定長度的隊列和不固定長度的隊列。

  > ArrayBlockQueue

    > 看BlockingQueue類的幫助文檔,其中有各個方法的差別對比的表格。

    > 隻有put方法和 take 方法才具有阻塞功能

  > 用3個空間的隊列來示範阻塞隊列的功能和效果

/*
 * 兩個線程向隊列中放資料,一個線程從隊列中取資料
 */
public class BlockingQueueTest {
      
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {
    </span><span style="color: #0000ff">final</span> BlockingQueue queue = <span style="color: #0000ff">new</span> ArrayBlockingQueue(3<span style="color: #000000">);
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;2;i++<span style="color: #000000">){
        </span><span style="color: #0000ff">new</span><span style="color: #000000"> Thread(){
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {
                </span><span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span><span style="color: #000000">){
                    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
                        Thread.sleep((</span><span style="color: #0000ff">long</span>)(Math.random()*1000<span style="color: #000000">));
                        System.out.println(Thread.currentThread().getName()
                                </span>+"準備放資料"<span style="color: #000000">);
                        queue.put(</span>1<span style="color: #000000">);
                        System.out.println(Thread.currentThread().getName()
                                </span>+"隊列目前有"+queue.size()+"個資料"<span style="color: #000000">);
                    } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }
    
    </span><span style="color: #0000ff">new</span><span style="color: #000000"> Thread(){
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {
            </span><span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span><span style="color: #000000">){
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
                    </span><span style="color: #008000">//</span><span style="color: #008000">将此處的睡眠時間分别改為100和1000,觀察運作結果</span>
                    Thread.sleep(1000<span style="color: #000000">);
                    System.out.println(Thread.currentThread().getName()
                            </span>+"準備取資料"<span style="color: #000000">);
                    queue.take();
                    System.out.println(Thread.currentThread().getName()
                            </span>+"隊列目前有"+queue.size()+"個資料"<span style="color: #000000">);
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {
                    e.printStackTrace();
                }
            }
        };
    }.start();
}
           

}

   >用兩個具有1個空間的隊列來實作同步通知的功能

/**
 * 改造之前的程式,用兩個具有1個空間的隊列來實作同步通知的功能
 * 使用阻塞隊列實作 
 * 子線程循環10次,接着主線程循環100次,接着又回到子線程循環10次,接着又 主線程循環100次,如此循環50次,請寫出程式
 * 
 * @author Administrator
 * 
 */
public class BlockingQueueCommunication {
      
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {
    </span><span style="color: #0000ff">final</span> Business5 business = <span style="color: #0000ff">new</span><span style="color: #000000"> Business5();
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {
        @Override
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {
            </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {
                business.sub(i);
            }
        }
    }).start();

    </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {
        business.main(i);
    }

}

</span><span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Business5 {
    BlockingQueue</span>&lt;Integer&gt; queue1 = <span style="color: #0000ff">new</span> ArrayBlockingQueue&lt;&gt;(1<span style="color: #000000">);
    BlockingQueue</span>&lt;Integer&gt; queue2 = <span style="color: #0000ff">new</span> ArrayBlockingQueue&lt;&gt;(1<span style="color: #000000">);
    </span><span style="color: #008000">//</span><span style="color: #008000">這種寫法叫 匿名構造方法,運作時機在任何構造方法之前,建立多少個對象就會調用多少次, 而static{} 靜态代碼塊在類加載的時候調用且隻調用一次</span>
           

{

try {

queue2.put(1);

} catch (InterruptedException e) {

e.printStackTrace();

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> sub(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {
        </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
            queue1.put(</span>1<span style="color: #000000">);
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {
            e.printStackTrace();
        }
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 100; j++<span style="color: #000000">) {
            System.out.println(</span>"sub thread sequence of " + j + ", loop of "
                    +<span style="color: #000000"> i);
        }
        </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
            queue2.take();
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {
            e.printStackTrace();
        }
    }

    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {
        </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
            queue2.put(</span>1<span style="color: #000000">);
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {
            e.printStackTrace();
        }
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 10; j++<span style="color: #000000">) {
            System.out.println(</span>"main thread sequence of " +<span style="color: #000000"> j
                    </span>+ ", loop of " +<span style="color: #000000"> i);
        }
        </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
            queue1.take();
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {
            </span><span style="color: #008000">//</span><span style="color: #008000"> TODO Auto-generated catch block</span>
           

繼續閱讀