• 选学校
  • 高中毕后选择什么学校好
  • 启蒙星
  • 北大青鸟课程介绍
  • 北大青鸟助你走上高级软件工程师修炼之路
  • 转行不是梦,学北大青鸟IT培训
  • 北大青鸟辉煌12年
  • 株洲北大青鸟校区升级

您现在的位置:株洲北大青鸟 >> >> 师资力量>> 技术天地

师资力量
开班信息
输入姓名手机号码预约试听课程
姓  名:*
手机号:*
创业摇篮班
开班日期:10月15日
招生人数:25
就业直通班
开班日期:10月31日
招生人数:25
就业精英班
开班日期:9月13日
招生人数:已满
技术天地
  • Java进阶:一个简单Thread缓冲池的实现
  • 发表日期:2009/7/19 14:47:05 阅读数:968  
  •  
  •           Java进阶:一个简单Thread缓冲池的实现

                                                                                                  株洲北大青鸟  叶盛

    在应用中,我们常常需要Thread缓冲池来做一些事以提高程序的效率和并发性。本文演示了如何利用Queue这种数据结构实现一个简单的Thread缓冲池。
      一个Thread缓冲池可以设计成以下这样:缓冲池由几个工作Thread和一个Queue组成,Client负责把任务放到Queue里面(put方法),而工作Thread就依次取出这些任务并执行它们(get方法)
      Queue的一个经典实现是使用一个循环数组(这个实现在很多数据结构的书上都有介绍),如一个大小为size的数组,这个循环数组可以被想象成首尾相连的一个环。oldest指向Queue中最老的数据所在的位置,next指向下一个可以放新数据的位置。
      放入一个新数据到next的位置后,需要更新nextnext = (next + 1) % size;
      从oldest位置取出一个数据后,需要更新oldest
    oldest = (oldest + 1) % size;
      当oldest == next的时候,Queue为空,

      当(next + 1) % size == oldest的时候,Queue为满。
      (注意:为了区分Queue为空和为满的情况,实际上Queue里面最多能放size-1个数据。)
      因为这个Queue会同时被多个
    线程访问,需要考虑在这种情况下Queue如何工作。首先,Queue需要是线程安全的,可以用Java里的synchronized关键字来确保同时只有一个Thread在访问Queue.
      我们还可以注意到当Queue为空的时候,get操作是无法进行的;Queue为满的时候,put操作又是无法进行的。在多线程访问遇到这种情况时,一般希望执行操作的线程可以等待(block)直到该操作可以进行下去。比如,但一个 Thread在一个空Queue上执行get方法的时候,这个 Thread应当等待(block),直到另外的Thread执行该Queueput方法后,再继续执行下去。在Java里面,Object对象的 wait (),notify()方法提供了这样的功能。

      
    把上面的内容结合起来,就是一个SyncQueue的类:

     
     

      public class SyncQueue {
     
     public SyncQueue(int size) {
        _array = new Object[size];
        _size = size;
        _oldest = 0;
        _next = 0;
       }
       public synchronized void put(Object o) {
        while (full()) {
         try {
          wait();
         } catch (InterruptedException ex) {
          throw new ExceptionAdapter(ex);
         }
        }
        _array[_next] = o;
        _next = (_next + 1) % _size;
        notify();
       }
       public synchronized Object get() {
        while (empty()) {
         try {
          wait();
         } catch (InterruptedException ex) {
          throw new ExceptionAdapter(ex);
         }
        }
        Object ret = _array[_oldest];
        _oldest = (_oldest + 1) % _size;
        notify();
        return ret;
       }
       protected boolean empty() {
        return _next == _oldest;
       }
       protected boolean full() {
        return (_next + 1) % _size == _oldest;
       }
       protected Object [] _array;
       protected int _next;
       protected int _oldest;
       protected int _size;
      }

      可以注意一下getput方法中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) _queue.get();
         task.run();
        }
       }
       protected SyncQueue _queue = null;
      }

      下面是一个使用这个Thread缓冲池的例子:

      //构造Thread
    缓冲池
      SyncQueue queue = new SyncQueue(10);
      for (int i = 0; i < 5; i ++) {
       new Thread(new Worker(queue)).start();
      }
      //使用Thread
    缓冲池
      Runnable task = new MyTask();
      queue.put(task);
      为了使本文中的代码尽可能简单,这个Thread缓冲池的实现是一个基本的框架。当使用到实际中时,一些其他功能也可以在这一基础上添加,比如异常处理,动态调整缓冲池大小等等。

     

上一篇:Java进阶:减少对象的创建提高java性能
下一篇:Java中static、this、super、final用法简谈
分享到:

版权所有 ©株洲健坤科技职业培训学校    学校地址:株洲市天元区黄山路205号健坤大厦(天元区消防中队对面)

咨询报名热线:400-8812-866    邮箱地址:4008812866@b.qq.com   备案号: 湘ICP备10202015号  

北大青鸟学费是多少 湖南北大青鸟怎么样
株洲北大青鸟好不好 株洲北大青鸟学费多少 株洲北大青鸟学校这么样
秒速时时彩官方网站