java中线程池的实现【原创】

  前些天由于用到多线程处理,所以想到线程池,搜集了网上的一些资料,再分析改进一下,有了下面的东西。
  首先是个读取配置文件的类:

  1package org.ofbiz.smsSend;
  2import java.io.File;
  3import java.io.FileInputStream;
  4import java.io.FileNotFoundException;
  5import java.io.FileOutputStream;
  6import java.io.IOException;
  7import java.util.Properties;
  8
  9/**
 10 * @author zxub 2005-11-11 16:44:55
 11 */

 12
 13public class UtilProperties
 14{
 15
 16    //设置默认的配置文件路径
 17    private String fileName = System.getProperty("user.dir")
 18            + "/base/config.properties";
 19    private Properties prop;
 20    private FileInputStream in;
 21    private FileOutputStream out;
 22
 23    /**
 24     * 自定义配置文件路径
 25     * @param fileName
 26     */

 27    public UtilProperties(String filePath)
 28    {        
 29        this.fileName = System.getProperty("user.dir")+filePath;
 30        getFile();
 31    }

 32
 33    public UtilProperties()
 34    {
 35        getFile();
 36    }

 37    
 38    /**
 39     * 获取配置文件
 40     */

 41    private void getFile()
 42    {
 43        File file = new File(this.fileName);
 44        try
 45        {
 46            in = new FileInputStream(file);
 47            prop = new Properties();
 48            // 载入文件
 49            prop.load(in);
 50            in.close();
 51        }

 52        catch (FileNotFoundException e)
 53        {
 54            System.err.println("配置文件config.properties找不到!!");
 55        }

 56        catch (IOException e)
 57        {
 58            System.err.println("读取配置文件config.properties错误!!");
 59        }
        
 60    }

 61
 62    /**
 63     * 列出所有的配置文件内容
 64     */

 65    public void list()
 66    {
 67        prop.list(System.out);
 68    }

 69
 70    /**
 71     * 指定配置项名称,返回配置值
 72     * 
 73     * @param itemName
 74     *            String
 75     * @return String
 76     */

 77
 78    public String getValue(String itemName)
 79    {
 80
 81        return prop.getProperty(itemName);
 82
 83    }

 84
 85    /**
 86     * 设置配置项名称及其值
 87     * 
 88     * @param itemName
 89     *            String
 90     * @param value
 91     *            String
 92     */

 93
 94    public void setValue(String itemName, String value)
 95    {
 96        prop.setProperty(itemName, value);
 97    }

 98
 99    /**
100     * 保存配置文件,指定文件名和抬头描述
101     * 
102     * @param fileName
103     *            String
104     * @param description
105     *            String
106     * @throws Exception
107     */

108    public void saveFile()
109    {
110        try
111        {
112            File f = new File(this.fileName);
113            out = new FileOutputStream(f);
114            prop.store(out, "");
115            out.close();
116        }

117        catch (FileNotFoundException e)
118        {
119            e.printStackTrace();
120        }

121        catch (IOException e)
122        {
123            System.err.println("配置文件config.properties写入错误!!");
124        }

125
126    }

127
128    /**
129     * 删除一个属性
130     * 
131     * @param value
132     *            String
133     */

134
135    public void deleteValue(String value)
136    {
137        prop.remove(value);
138    }

139    
140    public void changeFile(String filePath)
141    {
142        this.fileName = System.getProperty("user.dir")+filePath;
143        getFile();
144    }

145
146    
147    public static void main(String[] args)
148    {
149        UtilProperties up = new UtilProperties();
150        up.list();
151        up.changeFile("/logs/config.properties");
152        up.list();
153        System.out.println("\n"+up.getValue("tmpSavePath"));
154    }

155
156}

157

  接着,是要做事的类,我写了一个接口,只有一个方法doWork(),在线程池中,一旦一个线程获得一个工作任务,线程就会调用工作任务的doWork()方法。
package org.ofbiz.smsSend;

public interface Work
{
    
public abstract void doWork();
}

  然后,就是主要的线程池类了:
  1/**
  2 * @author zxub 2005-12-3 19:44:33
  3 */

  4package org.ofbiz.smsSend;
  5
  6import java.util.ArrayList;
  7import java.util.Iterator;
  8import java.util.LinkedList;
  9import java.util.Timer;
 10
 11public class ThreadPool
 12{    
 13    private static final UtilProperties utilProp = new UtilProperties();
 14    private static int minPools = Integer.parseInt(utilProp
 15        .getValue("minPools"));
 16    private static int maxPools = Integer.parseInt(utilProp
 17        .getValue("maxPools"));
 18    private static int checkThreadPeriod = Integer.parseInt(utilProp
 19        .getValue("checkThreadPeriod")) * 60 * 1000;
 20    private static ArrayList workThreadList; // 工作线程列表,保存所有的线程
 21    private static LinkedList taskList = null// 工作任务列表,保存将要执行的工作任务
 22    private static int totalThread = 0// 总线程数
 23    private static int freeThreadCount = 0// 未被使用的线程数目
 24    private java.util.Timer timer = null// 定时器
 25    private static Object o = new Object();
 26    
 27    private static ThreadPool pool=new ThreadPool();
 28    
 29    public static void setMinPools(int minPools)
 30    {
 31        ThreadPool.minPools = minPools;
 32    }

 33
 34    public static void setMaxPools(int maxPools)
 35    {
 36        ThreadPool.maxPools = maxPools;
 37    }

 38
 39    public static void setCheckThreadPeriod(int checkThreadPeriod)
 40    {
 41        ThreadPool.checkThreadPeriod = checkThreadPeriod;
 42    }

 43
 44    private ThreadPool()
 45    {        
 46        workThreadList = new ArrayList();
 47        taskList = new LinkedList();
 48        //初始化线程池
 49        for (int i = 0; i < ThreadPool.minPools; i++)
 50        {
 51            WorkerThread temp = new WorkerThread();
 52            totalThread = totalThread + 1;
 53            workThreadList.add(temp);
 54            temp.start();
 55            try
 56            {
 57                Thread.sleep(100);
 58            }

 59            catch (Exception e)
 60            {
 61            }

 62        }

 63        timer = new Timer(true); // 启动定时器
 64        timer.schedule(new CheckThreadTask(this), 0, checkThreadPeriod);
 65    }

 66    
 67    public static ThreadPool getInstance()
 68    {
 69        return pool;
 70    }

 71    
 72    public synchronized void run(Work work)
 73    {
 74        if (freeThreadCount == 0)
 75        {
 76            if (totalThread < maxPools)
 77            {
 78                WorkerThread temp = new WorkerThread();
 79                totalThread = totalThread + 1;
 80                workThreadList.add(temp);
 81                temp.start();
 82                synchronized (taskList)
 83                {
 84                    taskList.add(work);
 85                    taskList.notify();
 86                }

 87            }

 88            else
 89            {
 90                while (freeThreadCount == 0)
 91                {
 92                    try
 93                    {
 94                        Thread.sleep(200);
 95                    }

 96                    catch (InterruptedException e)
 97                    {
 98                    }

 99                }

100                synchronized (taskList)
101                {
102                    taskList.add(work);
103                    taskList.notify();
104                }

105            }

106        }

107        else
108        {
109            synchronized (taskList)
110            {
111                taskList.add(work);
112                taskList.notify();
113            }

114        }

115    }

116
117    /**
118     * 检查工作线程列表,将非活动状态的线程换成活动状态的线程,保证线程池中的线程可用
119     *
120     */

121    public synchronized void checkAllThreads()
122    {
123
124        Iterator threadIterator = workThreadList.iterator();
125
126        while (threadIterator.hasNext())
127        // 逐个遍厉
128            WorkerThread workThread = (WorkerThread) threadIterator.next();
129
130            if (!(workThread.isAlive()))
131            {
132                // 如果处在非活动状态时
133                workThread = new WorkerThread(); // 重新生成1个线程
134                workThread.start(); // 启动
135            }

136        }

137    }

138
139    public static void printInfo()
140    {
141        System.out.println("minPools:" + minPools);
142        System.out.println("maxPools:" + maxPools);
143        System.out.println("checkThreadPeriod:" + checkThreadPeriod);
144        System.out.println("totalThread=" + totalThread);
145        System.out.println("workThreadList.size()=" + workThreadList.size());
146    }

147   
148    /**
149     * 线程池中的工作线程类,由工作线程执行我们要进行的操作
150     */

151    class WorkerThread extends Thread
152    {
153        boolean running = true;
154        Work work;
155
156        public void run()
157        {
158            while (running)
159            {
160                synchronized (o)
161                {
162                    freeThreadCount++//一进来说明多了一个可用线程
163                }

164                synchronized (taskList)
165                {
166                    while (taskList.size() == 0//当工作任务列表为空时,等待
167                    {
168                        try
169                        {
170                            taskList.wait();
171                            if (!running) return;
172                        }

173                        catch (InterruptedException e)
174                        {
175                        }

176                    }

177                    synchronized (o)
178                    {
179                        freeThreadCount--//得到一个工作,可用线程要减1
180                    }

181                    work = (Work) taskList.removeLast(); //从任务列表处获得一个任务
182                    if (work == nullreturn;
183                }

184                work.doWork();
185            }

186        }

187    }

188}

189
  定时器自动查失效的线程,用到的方法如下:
 1package org.ofbiz.smsSend;
 2
 3import java.util.TimerTask;
 4
 5public class CheckThreadTask extends TimerTask
 6{
 7    private static boolean isRunning = false;
 8    private ThreadPool pool;
 9
10    public CheckThreadTask(ThreadPool pool)
11    {
12        this.pool = pool;
13    }

14
15    public void run()
16    {
17        if (!isRunning)
18        {
19            isRunning = true;
20            pool.checkAllThreads();
21            isRunning = false;
22        }

23    }

24}

25
  最后,配置文件的内容如下
1#----------------线程池配置信息-----------------
2#
3#线程池最小线程
4minPools=10
5#线程池最大线程
6maxPools=100
7#检查线程池中线程的周期(分钟)
8checkThreadPeriod=5
  ok,要用的时候,调用方法如下:
1ThreadPool.getInstance().run(new (实现了work接口的类));
原文地址:https://www.cnblogs.com/zxub/p/293806.html