<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    java線程池的應用

    Posted on 2010-10-14 13:10 myfavorite 閱讀(2352) 評論(0)  編輯  收藏
            一直是在NET的平臺做應用軟件的開發的,在上一個項目完成后,公司定下新的項目改為在java平臺開發,說是行業要求。這可是要了我的命。我對java可是一點都不了解,更搞不懂這java,jsp等等這些的差別,突然要搞這個,而且項目還緊,郁悶死。都有想要離職的念頭。可是總在猶豫不決中,遲遲下不了決心...... 

            不管別的,只要在公司呆著,就得干活。公司可不會養什么閑人。
            先就當學習吧。安裝java的開發環境:jdk,開發工具:MyEclipse,在趕項目的同事開始Java的學習。

           第一個任務是編寫一個java的后臺服務,主要處理是解析報文數據。在NET的開發工具下,可以直接建立一個Windows Service項目。在網上搜索了下,java的平臺下,都是將java的應用轉為Windows Service,這就用了半天的時間,郁悶死。趕的急,先就寫java應用吧。首先連接數據庫,下載相關包文件,配置連接,搜索相關的代碼,抄過來后修改先關連接參數后運行,結果不是Connect Refused,就是Error establishing socket,又郁悶的要死。看網上說的可能是數據庫安裝的問題,但是又不想重新安裝數據庫,實在沒有招了,試著連別人的數據庫,奇怪這就可以連接了!查了下數據庫的區別,正常連接的數據庫版本是Enterprise Evaluation Edition,本地數據庫版本是Developer Edition。可能是這個原因吧。反正搞的很郁悶,這又用了近半天的時間。在寫應用的過程中,使用到substring函數,又要抓狂了。java下的這個函數的參數和其他語言下該函數的參數有差別,剛開始沒注意,執行時總是結果不對。搞了半天才發現這個問題。

             哎,慢慢做吧。今天要用到線程池的應用,在網上看到一段不錯的代碼,抄錄過來學習下。

             所謂線程池,即在進程啟動時,同時生成一定數量的線程,把他們放入一個容器中,這樣,當有需求時,從池中取出一個線程去處理請求,當池里的線程用完時,在有請求時則只能等待。 

            下面是一個簡單的java例子,來示范java中線程池的應用。

            示例程序由三個類構成,主要實現一下功能:每輸入一行字符串,就請求一個線程去模擬處理
            第一個是TestThreadPool類,它是一個測試程序,用來模擬客戶端的請求,當你運行它時,系統首先會顯示線程池的初始化信息,然后提示你從鍵盤上輸入字符串,并按下回車鍵,這時你會發現屏幕上顯示信息,告訴你某個線程正在處理你的請求,如果你快速地輸入一行行字符串,那么你會發現線程池中不斷有線程被喚醒,來處理你的請求,在本例中,我創建了一個擁有10個線程的線程池,如果線程池中沒有可用線程了,系統會提示你相應的警告信息,但如果你稍等片刻,那你會發現屏幕上會陸陸續續提示有線程進入了睡眠狀態,這時你又可以發送新的請求了。

            第二個類是ThreadPoolManager類,顧名思義,它是一個用于管理線程池的類,它的主要職責是初始化線程池,并為客戶端的請求分配不同的線程來進行處理,如果線程池滿了,它會對你發出警告信息。

            最后一個類是SimpleThread類,它是Thread類的一個子類,它才真正對客戶端的請求進行處理,SimpleThread在示例程序初始化時都處于睡眠狀態,但如果它接受到了ThreadPoolManager類發過來的調度信息,則會將自己喚醒,并對請求進行處理。
      
            首先我們來看一下TestThreadPool類的源碼:
    // TestThreadPool.java
    import java.io.*;

    public class TestThreadPool {
        
    public static void main(String[] args) {
            
    try {
                BufferedReader br 
    = new BufferedReader(new InputStreamReader(
                        System.in));
                String s;
                ThreadPoolManager manager 
    = new ThreadPoolManager(10);
                
    while ((s = br.readLine()) != null{
                    manager.process(s);
                }

            }
     catch (IOException e) {
            }

        }

    }

            由于此測試程序用到了輸入輸入類,因此第1行導入了JAVA的基本IO處理包,在第11行中,我們創建了一個名為manager的類,它給ThreadPoolManager類的構造函數傳遞了一個值為10的參數,告訴ThreadPoolManager類:我要一個有10個線程的池,給我創建一個吧!第12行至15行是一個無限循環,它用來等待用戶的鍵入,并將鍵入的字符串保存在s變量中,并調用ThreadPoolManager類的process方法來將這個請求進行處理。

            下面我們再進一步跟蹤到ThreadPoolManager類中去,以下是它的源代碼:
    //ThreadPoolManager.java 
    import java.util.*;

    class ThreadPoolManager {

        
    private int maxThread;
        
    public Vector vector;

        
    public void setMaxThread(int threadCount) {
            maxThread 
    = threadCount;
        }


        
    public ThreadPoolManager(int threadCount) {
            setMaxThread(threadCount);
            System.out.println(
    "Starting thread pool");
            vector 
    = new Vector();
            
    for (int i = 1; i <= 10; i++{
                SimpleThread thread 
    = new SimpleThread(i);
                vector.addElement(thread);
                thread.start();
            }

        }


        
    public void process(String argument) {
            
    int i;
            
    for (i = 0; i < vector.size(); i++{
                SimpleThread currentThread 
    = (SimpleThread) vector.elementAt(i);
                
    if (!currentThread.isRunning()) {
                    System.out.println(
    "Thread " + (i + 1+ " is processing:"
                            
    + argument);
                    currentThread.setArgument(argument);
                    currentThread.setRunning(
    true);
                    
    return;
                }

            }

            
    if (i == vector.size()) {
                System.out.println(
    "pool is full, try in another time.");
            }

        }

    }
    // end of class ThreadPoolManager

            我們先關注一下這個類的構造函數,然后再看它的process()方法。第16-24行是它的構造函數,首先它給ThreadPoolManager類的成員變量maxThread賦值,maxThread表示用于控制線程池中最大線程的數量。第18行初始化一個數組vector,它用來存放所有的SimpleThread類,這時候就充分體現了JAVA語言的優越性與藝術性:如果你用C語言的話,至少要寫100行以上的代碼來完成vector的功能,而且C語言數組只能容納類型統一的基本數據類型,無法容納對象。好了,閑話少說,第19-24行的循環完成這樣一個功能:先創建一個新的SimpleThread類,然后將它放入vector中去,最后用thread.start()來啟動這個線程,為什么要用start()方法來啟動線程呢?因為這是JAVA語言中所規定的,如果你不用的話,那這些線程將永遠得不到激活,從而導致本示例程序根本無法運行。
      
            下面我們再來看一下process()方法,第30-40行的循環依次從vector數組中選取SimpleThread線程,并檢查它是否處于激活狀態(所謂激活狀態是指此線程是否正在處理客戶端的請求),如果處于激活狀態的話,那繼續查找vector數組的下一項,如果vector數組中所有的線程都處于激活狀態的話,那它會打印出一條信息,提示用戶稍候再試。相反如果找到了一個睡眠線程的話,那第35-38行會對此進行處理,它先告訴客戶端是哪一個線程來處理這個請求,然后將客戶端的請求,即字符串argument轉發給SimpleThread類的setArgument()方法進行處理,并調用SimpleThread類的setRunning()方法來喚醒當前線程,來對客戶端請求進行處理。

      可能你還對setRunning()方法是怎樣喚醒線程的有些不明白,那我們現在就進入最后一個類:SimpleThread類,它的源代碼如下:

    //SimpleThread.java 
    class SimpleThread extends Thread {
        
    private boolean runningFlag;
        
    private String argument;

        
    public boolean isRunning() {
            
    return runningFlag;
        }


        
    public synchronized void setRunning(boolean flag) {
            runningFlag 
    = flag;
            
    if (flag)
                
    this.notify();
        }


        
    public String getArgument() {
            
    return this.argument;
        }


        
    public void setArgument(String string) {
            argument 
    = string;
        }


        
    public SimpleThread(int threadNumber) {
            runningFlag 
    = false;
            System.out.println(
    "thread " + threadNumber + "started.");
        }


        
    public synchronized void run() {
            
    try {
                
    while (true{
                    
    if (!runningFlag) {
                        
    this.wait();
                    }
     else {
                        System.out.println(
    "processing " + getArgument()
                                
    + " done.");
                        sleep(
    5000);
                        System.out.println(
    "Thread is sleeping");
                        setRunning(
    false);
                    }

                }

            }
     catch (InterruptedException e) {
                System.out.println(
    "Interrupt");
            }

        }
    // end of run()
    }
    // end of class SimpleThread

     

          用戶在run()接口中寫入自己的應用處理邏輯。那么怎么來控制線程的睡眠與喚醒呢?其實很簡單,JAVA語言為所有的對象都內置了wait()和notify()方法,當一個線程調用wait()方法時,則線程進入睡眠狀態,就像停在了當前代碼上了,也不會繼續執行它以下的代碼了,當調用notify()方法時,則會從調用wait()方法的那行代碼繼續執行以下的代碼,這個過程有點像編譯器中的斷點調試的概念。以本程序為例,第38行調用了wait()方法,則這個線程就像凝固了一樣停在了38行上了,如果在第13行進行一個notify()調用的話,那線程會從第38行上喚醒,繼續從第39行開始執行以下的代碼了。

      通過以上的講述,現在就不難理解SimpleThread類了,第9-14行通過設置一個標志runningFlag激活當前線程,第25-29行是SimpleThread類的構造函數,它用來告訴客戶端啟動的是第幾號進程。第31-50行則是我實現的run()接口,它實際上是一個無限循環,在循環中首先判斷一下標志runningFlag,如果沒有runningFlag為false的話,那線程處理睡眠狀態,否則第42-45行會進行真正的處理:先打印用戶鍵入的字符串,然后睡眠5秒鐘,為什么要睡眠5秒鐘呢?如果你不加上這句代碼的話,由于計算機處理速度遠遠超過你的鍵盤輸入速度,因此你看到的總是第1號線程來處理你的請求,從而達不到演示效果。最后第45行調用setRunning()方法又將線程置于睡眠狀態,等待新請求的到來。

      最后還有一點要注意的是,如果在一個方法中調用了wait()和notify()函數,那一定要將此方法置為同步的,即synchronized,否則在編譯時會報錯,并得到一個莫名其妙的消息:“current thread not owner”(當前線程不是擁有者)。


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久久高清免费视频| 国产2021精品视频免费播放| 国产精品冒白浆免费视频| 亚洲一级毛片中文字幕| 91黑丝国产线观看免费| 亚洲另类春色国产精品| A在线观看免费网站大全| 亚洲另类无码专区首页| 免费观看亚洲人成网站| 亚欧洲精品在线视频免费观看| 国产亚洲欧洲Aⅴ综合一区| 日本免费电影一区二区| 亚洲制服丝袜一区二区三区| 欧美三级在线电影免费| 国产亚洲美女精品久久| 国产综合精品久久亚洲| 国产成人无码区免费网站| 亚洲黑人嫩小videos| 女人被免费视频网站| 免费在线观看一区| 亚洲国产另类久久久精品小说| 99热在线免费观看| 亚洲综合精品成人| 国产国拍精品亚洲AV片 | 拍拍拍无挡视频免费观看1000| 亚洲一区精品中文字幕| 午夜小视频免费观看| 九九免费精品视频在这里| 亚洲午夜久久影院| 日韩免费无砖专区2020狼| 中国好声音第二季免费播放| 激情综合亚洲色婷婷五月| 国产亚洲精品资在线| 国产福利在线免费| 国产成人自产拍免费视频| 亚洲精品二三区伊人久久| 久久久久亚洲精品中文字幕 | 波多野结衣免费视频观看| 久久国产精品萌白酱免费| 亚洲国产无线乱码在线观看| 亚洲AV永久无码精品成人|