• 用Stack实现对多线程的管理范例


    多线程就是并发技术,当线程数量超过一定数量时,系统响应就会变慢,所以就必须对线程数量进行控制,那么采用哪种控制方法呢?采用Stack类模仿堆栈,之所以说是模仿,就是因为Stack类毕竟不是真实的堆栈,push和pop操作也并非是真正的入栈和出栈操作!程序思路是创建一个线程池管理类ThreadPool类,这个类的作用是用于创建指定数量的工作线程并压入栈中,此外还负责唤醒线程进行工作(方法是performedWork(Object data)),还有一个将执行完任务的线程重新压入栈中的方法push(),在线程池类内部有一个嵌套的工作线程WorkerThread类,这个类就是具体负责执行任务的工作线程,但是任务的具体执行者是由接口Worker或继承了该接口的实际类完成的。这里有几个关键点,一个数据对象,在创建了线程但还没有传入data对象时线程是一直处于wait()阻塞状态中。只有通过wake(Object data)方法进行唤醒并工作。

    例程如下:

    package thread.test;


    import java.util.Stack;


    public class StackThread {
         static class WorkProcess implements Worker{
            @Override
            public void run(Object data) {
                System.out.println(data);
            }  
          }
         public static void main(String[] args) throws Exception {
                     WorkProcess wp=new WorkProcess(); 
                    ThreadPool tp = new ThreadPool(wp.getClass(),10);
                     for(int i=0;i<11;i++)  //输出的顺序是没有先后的,第十一个线程为额外线程
                  tp.performedWork("function#"+i);  
         }  
    }
    class ThreadPool{
          class WorkerThread extends Thread{
              private Object data;
              private Worker worker;
              //工作线程需要两个参数,标识符和工作接口,还需要一个数据用于运行run(Object data)方法,在得到data对象之前,线程一直处于阻塞状态
              public WorkerThread(String idoilt,Worker worker){
                  super(idoilt);
                  this.worker=worker; 
                 data=null;
              }
             synchronized public void wake(Object data){
                  this.data=data;
                  this.notify();
             }
            @Override
            synchronized public void run(){
                   boolean stop=false;
                    while(!stop){
                   if(data==null){
                   try {
                           this.wait();
                    } catch (InterruptedException e) {
                           e.printStackTrace();
                    }
                 }
                if(data!=null){ //下面这两句话可能不会同时输出,即线程会在输出第一句话之后切换到另外一个线程
                   System.out.println(this.getName());
                   worker.run(data);
              }
              data=null;
         stop=push(this);
              }  
             }
         }

          @SuppressWarnings("rawtypes")
             private Stack  _waiting;        //被所有线程所共享的对象,所以必须同步,用于存放所有的工作线程
          @SuppressWarnings("rawtypes")
          private Class  _workerClass;
          int _max;
         @SuppressWarnings({ "unchecked", "rawtypes" })
         public ThreadPool(Class workerClass,int max)throws Exception{
         _workerClass=workerClass; 
         _max=max;
          _waiting =new Stack();
         Worker wo;
         WorkerThread wt;
         for(int i=0;i<_max;i++){//创建一定数量的工作线程
             wo=(Worker)_workerClass.newInstance(); //产生一个新的实例,均是继承于Worker接口。
             wt=new WorkerThread("worker#"+i,wo);
             wt.start();//请网友思考一下为什么这里要启动方法,而不在performedWork方法中启动呢?但实际确实必须在这里启动
            _waiting.push(wt);
          }
       }
        //执行工作线程方法,传入data对象唤醒线程进行工作
        public void performedWork(Object data)throws InstantiationException, IllegalAccessException{
             WorkerThread w= null;
             synchronized(_waiting){
               if(_waiting.empty()){
                   w=new WorkerThread("addtional thread",
                               (Worker)_workerClass.newInstance());
                     w.start();
                 }
                else {
                    w=(WorkerThread)_waiting.pop();
                   //w.start();  //这条语句是错的,会引发一个IllegalThreadStateException异常,具体原因我也不清楚,你想清楚了,可以告诉我
                    //在这里启动可能就会导致wake方法失去意义,因为唤醒线程之前必须处于阻塞状态,也就是必须启动线程!在这里启动并不会立即启动
                    //线程,而是会继续往下执行wake方法,由于线程未启动就唤醒就会出错! 
                 }
      
                 w.wake(data);

              }
         }
         @SuppressWarnings("unchecked")
          public boolean push(WorkerThread obj){
               boolean isPOP=false;
               synchronized(_waiting){
                       if(_waiting.size()<_max){
                              _waiting.push(obj);
                              isPOP=true;
                       }
                   }
                return isPOP;
         }
    }
    interface Worker {
                public void run(Object data);
    }
    这辆直升机是九江红鹰制造的,确实非常不错,看起来真酷! 

  • 相关阅读:
    Golang调用windows下的dll动态库中的函数
    Golang 编译成 DLL 文件
    go 通过nginx代理后获取用户ip
    idea教程--Maven 骨架介绍
    idea教程--快速插入依赖
    Java开发名词解释
    Android Studio安装
    Java基础--Eclipse关联Java源码
    【排序基础】3、随机生成排序算法 测试用例
    【排序基础】2、使用模板(泛型)编写选择排序算法
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3141286.html
Copyright © 2020-2023  润新知