熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

一個簡單的 Thread 緩沖池的實現

2022-06-13   來源: Java高級技術 

  在應用中我們常常需要Thread緩沖池來做一些事以提高程序的效率和並發性本文演示了如何利用Queue這種數據結構實現一個簡單的Thread緩沖池
  
  一個Thread緩沖池可以設計成以下這樣緩沖池由幾個工作Thread和一個Queue組成Client負責把任務放到Queue裡面(put方法)而工作Thread就依次取出這些任務並執行它們(get方法)
  
  Queue的一個經典實現是使用一個循環數組(這個實現在很多數據結構的書上都有介紹)如一個大小為size的數組這個循環數組可以被想象成首尾相連的一個環oldest指向Queue中最老的數據所在的位置next指向下一個可以放新數據的位置
  
  放入一個新數據到next的位置後需要更新nextnext = (next + ) % size;
  
  從oldest位置取出一個數據後需要更新oldestoldest = (oldest + ) % size;
  
  當oldest == next的時候Queue為空
  
  當(next + ) % size == oldest的時候Queue為滿
  
  (注意為了區分Queue為空和為滿的情況實際上Queue裡面最多能放size個數據
  
  因為這個Queue會同時被多個線程訪問需要考慮在這種情況下Queue如何工作首先Queue需要是線程安全的可以用Java裡的synchronized關鍵字來確保同時只有一個Thread在訪問Queue
  
  我們還可以注意到當Queue為空的時候get操作是無法進行的當Queue為滿的時候put操作又是無法進行的在多線程訪問遇到這種情況時一般希望執行操作的線程可以等待(block)直到該操作可以進行下去比如但一個Thread在一個空Queue上執行get方法的時候這個 Thread應當等待(block)直到另外的Thread執行該Queue的put方法後再繼續執行下去在Java裡面Object對象的 wait()notify()方法提供了這樣的功能
  
  把上面的內容結合起來就是一個SyncQueue的類
  
  public class SyncQueue {
  
  public SyncQueue(int size) {
  _array = new Object[size];
  _size = size;
  _oldest = ;
  _next = ;
  }
  
  public synchronized void put(Object o) {
  while (full()) {
  try {
  wait();
  } catch (InterruptedException ex) {
  throw new ExceptionAdapter(ex);
  }
  }
  _array[_next] = o;
  _next = (_next + ) % _size;
  notify();
  }
  
  public synchronized Object get() {
  while (empty()) {
  try {
  wait();
  } catch (InterruptedException ex) {
  throw new ExceptionAdapter(ex);
  }
  }
  Object ret = _array[_oldest];
  _oldest = (_oldest + ) % _size;
  notify();
  return ret;
  }
  
  protected boolean empty() {
  return _next == _oldest;
  }
  
  protected boolean full() {
  return (_next + ) % _size == _oldest;
  }
  
  protected Object [] _array;
  protected int _next;
  protected int _oldest;
  protected int _size;
  }
  
  可以注意一下get和put方法中while的使用如果換成if是會有問題的這是個很容易犯的錯誤;)
  
  在以上代碼中使用了ExceptionAdapter這個類它的作用是把一個checked Exception包裝成RuntimeException詳細的說明可以參考我的避免在Java中使用Checked Exception一文
  
  接下來我們需要一個對象來表現Thread緩沖池所要執行的任務可以發現JDK中的Runnable interface非常合適這個角色
  
  最後剩下工作線程的實現就很簡單了從SyncQueue裡取出一個Runnable對象並執行它
  
  public class Worker implements Runnable {
  
  public Worker(SyncQueue queue) {
  _queue = queue;
  }
  
  public void run() {
  while (true) {
  Runnable task = (Runnable) _queueget();
  taskrun();
  }
  }
  
  protected SyncQueue _queue = null;
  
  }
  
  下面是一個使用這個Thread緩沖池的例子
  
  //構造Thread緩沖池
  
  SyncQueue queue = new SyncQueue();
  for (int i = ; i < ; i ++) {
  new Thread(new Worker(queue))start();
  }
  
  //使用Thread緩沖池
  
  Runnable task = new MyTask();
  queueput(task);
  
  為了使本文中的代碼盡可能簡單這個Thread緩沖池的實現是一個基本的框架當使用到實際中時一些其他功能也可以在這一基礎上添加比如異常處理動態調整緩沖池大小等等
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27553.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.