最近用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"));
- }
- }