最近用JAVA开发并发多线程机制,一般我们开发的程序都是只有一个主线程的,即MAIN()函数开始,但是在一些特别的场合下,比如服务器接受命令的 过程,可能需要同时处理多个客户端发送的命令,这时就需要征对每个客户建立一个线程。这样建立多线程程序,多线程可以使得在同一时间间隔内,执行多个指 令,以至于多个逻辑处理并发的运行。在JAVA中有二种方法可以定义一个线程:Runnable接口与Thread类,最终都是由Thread类的 start()方法启动线程,而真正执行的命令在run()方法中,另外线程有几种状态:执行,终止,休眠,挂起等。在某种条件下各个状态之间可以互相转换。
有二种比较重要模型:
生产者-消费者模型,就是由一个线程生产任务,而另外一个线程执行任务,二个线程之间有一个共享数据区,这种数据结构可以用队列来表示,但是必须是并发同 步的,也就是就共享数据队列同一时间只能允许一个线程进行访问。这种机制叫做同步访问,在JAVA里面用关键字synchorinized 来标识对象是同步并发访问的。
线程池模型,就是说开始由值守线程创建N个工作线程,并启动它们,它们的状态初始为空闲。然后值守线程到工作队列中取出一个工作任务,同时从线程池中取出 一空闲线程来执行此工作任务,执行完该任务后,把该工作线程由运行变为空闲状态,这样不断的从工作队列中取出任务由线程池中的空闲线程进行执行完成。线程 池模型不用为每个任务都创建一个线程,只需初始时创建N个线程,然后一直用这N个线程去执行工作队列中的任务,大大的减少了线程的启动,终止的开销。
总之,多线程编程的关键是线程类的设计,以及共享数据的设计,同时注意区分哪些是多线程可能访问,哪些是各线程自已私有的,还有就是线程的状态变换,比如挂起的线程何时需要唤醒。等等问题。。
一个线程池模型的实例:
ThreadPool.java
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.Timer;
- public class ThreadPool
- {
- private static final UtilProperties utilProp = new UtilProperties();
- private static int minPools = Integer.parseInt(utilProp
- .getValue("minPools"));
- private static int maxPools = Integer.parseInt(utilProp
- .getValue("maxPools"));
- private static int checkThreadPeriod = Integer.parseInt(utilProp
- .getValue("checkThreadPeriod")) * 60 * 1000;
- private static ArrayList<WorkerThread> workThreadList; //
- private static LinkedList<Work> taskList = null; //
- private static int totalThread = 0; //
- private static int freeThreadCount = 0; //
- private java.util.Timer timer = null; //
- private static Object o = new Object();
- private static ThreadPool pool=new ThreadPool();
- public static void setMinPools(int minPools)
- {
- ThreadPool.minPools = minPools;
- }
- public static void setMaxPools(int maxPools)
- {
- ThreadPool.maxPools = maxPools;
- }
- public static void setCheckThreadPeriod(int checkThreadPeriod)
- {
- ThreadPool.checkThreadPeriod = checkThreadPeriod;
- }
- private ThreadPool()
- {
- workThreadList = new ArrayList<WorkerThread>();
- taskList = new LinkedList<Work>();
- //
- for (int i = 0; i < ThreadPool.minPools; i++)
- {
- WorkerThread temp = new WorkerThread();
- totalThread = totalThread + 1;
- workThreadList.add(temp);
- temp.start();
- try
- {
- Thread.sleep(100);
- }
- catch (Exception e)
- {
- }
- }
- timer = new Timer(true); //
- timer.schedule(new CheckThreadTask(this), 0, checkThreadPeriod);
- }
- public static ThreadPool getInstance()
- {
- return pool;
- }
- public synchronized void run(Work work)
- {
- if (freeThreadCount == 0)
- {
- if (totalThread < maxPools)
- {
- WorkerThread temp = new WorkerThread();
- totalThread = totalThread + 1;
- workThreadList.add(temp);
- temp.start();
- synchronized (taskList)
- {
- taskList.add(work);
- taskList.notify();
- }
- }
- else
- {
- while (freeThreadCount == 0)
- {
- try
- {
- Thread.sleep(200);
- }
- catch (InterruptedException e)
- {
- }
- }
- synchronized (taskList)
- {
- taskList.add(work);
- taskList.notify();
- }
- }
- }
- else
- {
- synchronized (taskList)
- {
- taskList.add(work);
- taskList.notify();
- }
- }
- }
- /** *//**
- *
- *
- */
- public synchronized void checkAllThreads()
- {
- Iterator<WorkerThread> threadIterator = workThreadList.iterator();
- while (threadIterator.hasNext())
- { //
- WorkerThread workThread = (WorkerThread) threadIterator.next();
- if (!(workThread.isAlive()))
- {
- //
- workThread = new WorkerThread(); //
- workThread.start(); //
- }
- }
- }
- public static void printInfo()
- {
- System.out.println("minPools:" + minPools);
- System.out.println("maxPools:" + maxPools);
- System.out.println("checkThreadPeriod:" + checkThreadPeriod);
- System.out.println("totalThread=" + totalThread);
- System.out.println("workThreadList.size()=" + workThreadList.size());
- }
- class WorkerThread extends Thread
- {
- boolean running = true;
- Work work;
- public void run()
- {
- while (running)
- {
- synchronized (o)
- {
- freeThreadCount++; //進來說明多了一個可用線程
- }
- synchronized (taskList)
- {
- while (taskList.size() == 0) //當工作任務列表為空時等待
- {
- try
- {
- taskList.wait();
- if (!running) return;
- }
- catch (InterruptedException e)
- {
- }
- }
- synchronized (o)
- {
- freeThreadCount--; //得到一個工作,可用線程減一
- }
- work = (Work) taskList.removeLast(); //從人物列裱中獲得一個任務
- if (work == null) return;
- }
- work.doWork();
- }
- }
- }
- }
CheckThreadTask.java
- import java.util.TimerTask;
- public class CheckThreadTask extends TimerTask
- {
- private static boolean isRunning = false;
- private ThreadPool pool;
- public CheckThreadTask(ThreadPool pool)
- {
- this.pool = pool;
- }
- public void run()
- {
- if (!isRunning)
- {
- isRunning = true;
- pool.checkAllThreads();
- isRunning = false;
- }
- }
- }
Work.java
- public interface Work
- {
- public abstract void doWork();
- }
UtilProperties.java
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.Properties;
- public class UtilProperties
- {
- //
- private String fileName = System.getProperty("user.dir")
- + "/base/config.properties";
- private Properties prop;
- private FileInputStream in;
- private FileOutputStream out;
- /** *//**
- *
- * @param fileName
- */
- public UtilProperties(String filePath)
- {
- this.fileName = System.getProperty("user.dir")+filePath;
- getFile();
- }
- public UtilProperties()
- {
- getFile();
- }
- /** *//**
- *
- */
- private void getFile()
- {
- File file = new File(this.fileName);
- try
- {
- in = new FileInputStream(file);
- prop = new Properties();
- //
- prop.load(in);
- in.close();
- }
- catch (FileNotFoundException e)
- {
- System.err.println("配置文件config.properties找不到!!");
- }
- catch (IOException e)
- {
- System.err.println("讀取配置文件config.properties錯誤!!");
- }
- }
- /** *//**
- * 列出所有配置文件內容
- */
- public void list()
- {
- prop.list(System.out);
- }
- /** *//**
- *
- *
- * @param itemName
- * String
- * @return String
- */
- public String getValue(String itemName)
- {
- return prop.getProperty(itemName);
- }
- /** *//**
- *
- *
- * @param itemName
- * String
- * @param value
- * String
- */
- public void setValue(String itemName, String value)
- {
- prop.setProperty(itemName, value);
- }
- /** *//**
- *
- *
- * @param fileName
- * String
- * @param description
- * String
- * @throws Exception
- */
- public void saveFile()
- {
- try
- {
- File f = new File(this.fileName);
- out = new FileOutputStream(f);
- prop.store(out, "");
- out.close();
- }
- catch (FileNotFoundException e)
- {
- e.printStackTrace();
- }
- catch (IOException e)
- {
- System.err.println("配置文件config.properties寫入錯誤!!");
- }
- }
- /** *//**
- *
- *
- * @param value
- * String
- */
- public void deleteValue(String value)
- {
- prop.remove(value);
- }
- public void changeFile(String filePath)
- {
- this.fileName = System.getProperty("user.dir")+filePath;
- getFile();
- }
- public static void main(String[] args)
- {
- UtilProperties up = new UtilProperties();
- up.list();
- // up.changeFile("/logs/config.properties");
- // up.list();
- System.out.println("/n"+up.getValue("tmpSavePath"));
- }
- }