java socket 線程池echo服務(wù)器

java socket系列文章
java socket 單線程echo服務(wù)器
java socket 多線程echo服務(wù)器
java socket 線程池echo服務(wù)器

java socket 多線程echo服務(wù)器這篇文章中累榜,改善了單線程echo服務(wù)器中只能處理一個(gè)客戶端請(qǐng)求的弊端,利用一個(gè)客戶端對(duì)應(yīng)一個(gè)線程的方法型酥,達(dá)到處理多個(gè)客戶端的目的秕噪。

但是,每個(gè)新線程都會(huì)消耗系統(tǒng)資源:

  1. 創(chuàng)建一個(gè)線程會(huì)占用 CPU 周期恋追,而且每個(gè)線程都會(huì)建立自己的數(shù)據(jù)結(jié)構(gòu)(如,棧),也要消耗系統(tǒng)內(nèi)存嘁酿。
  2. 當(dāng)一個(gè)線程阻塞時(shí),JVM 將保存其狀態(tài)男应,選擇另外一個(gè)線程運(yùn)行闹司,并在上下文轉(zhuǎn)換(context switch)時(shí)恢復(fù)阻塞線程的狀態(tài)。隨著線程數(shù)的增加沐飘,線程將消耗越來(lái)越多的系統(tǒng)資源游桩,這將最終導(dǎo)致系統(tǒng)花費(fèi)更多的時(shí)間來(lái)處理上下文轉(zhuǎn)換盒線程管理,更少的時(shí)間來(lái)對(duì)連接進(jìn)行服務(wù)耐朴。

在這種情況下借卧,加入一個(gè)額外的線程實(shí)際上可能增加客戶端總服務(wù)的時(shí)間。當(dāng)線程數(shù)目過(guò)多的時(shí)候筛峭,必然導(dǎo)致每個(gè)客戶端請(qǐng)求的處理時(shí)間增長(zhǎng)铐刘,使用戶體驗(yàn)明顯變差。

我們可以通過(guò)限制線程總數(shù)并重復(fù)使用線程來(lái)避免這個(gè)問(wèn)題影晓。我們讓服務(wù)器在啟動(dòng)時(shí)創(chuàng)建一個(gè)由固定線程數(shù)量組成的線程池镰吵,線程池的工作原理:

  1. 當(dāng)一個(gè)新的客戶端連接請(qǐng)求傳入服務(wù)器,它將交給線程池中的一個(gè)線程處理挂签,
  2. 該線程處理完這個(gè)客戶端之后疤祭,又返回線程池,繼續(xù)等待下一次請(qǐng)求饵婆。
  3. 如果連接請(qǐng)求到達(dá)服務(wù)器時(shí)画株,線程池中所有的線程都已經(jīng)被占用,它們則在一個(gè)隊(duì)列中等待啦辐,直到有空閑的線程可用谓传。

與一客戶一線程服務(wù)器一樣,線程池服務(wù)器首先創(chuàng)建一個(gè) ServerSocket 實(shí)例芹关。
然后創(chuàng)建 N 個(gè)線程续挟,每個(gè)線程反復(fù)循環(huán),從(共享的)ServerSocket 實(shí)例接收客戶端連接侥衬。當(dāng)多個(gè)線程同時(shí)調(diào)用一個(gè) ServerSocket 實(shí)例的 accept()方法時(shí)诗祸,它們都將阻塞等待跑芳,直到一個(gè)新的連接成功建立,然后系統(tǒng)選擇一個(gè)線程直颅,為建立起的連接提供服務(wù)博个,其他線程則繼續(xù)阻塞等待。
線程在完成對(duì)一個(gè)客戶端的服務(wù)后功偿,繼續(xù)等待其他的連接請(qǐng)求盆佣,而不終止。如果在一個(gè)客戶端連接被創(chuàng)建時(shí)械荷,沒(méi)有線程在 accept()方法上阻塞(即所有的線程都在為其他連接服務(wù))共耍,系統(tǒng)則將新的連接排列在一個(gè)隊(duì)列中,直到下一次調(diào)用 accept()方法吨瞎。

客戶端代碼:
public class Client {
    public static void main(String[] args) throws IOException {      
        Socket client = new Socket("127.0.0.1", 20012);  
        //客戶端請(qǐng)求與本機(jī)在20011端口建立TCP連接 
        client.setSoTimeout(10000);             
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); 
        //獲取鍵盤輸入        
        PrintStream out = new PrintStream(client.getOutputStream());          
        //獲取Socket的輸出流痹兜,用來(lái)發(fā)送數(shù)據(jù)到服務(wù)端                  
        BufferedReader buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));  
        //獲取Socket的輸入流,用來(lái)接收從服務(wù)端發(fā)送過(guò)來(lái)的數(shù)據(jù) 
        boolean flag = true;  
        while(flag){  
            System.out.print("輸入信息:");  
            String str = input.readLine();  
            out.println(str);  
            //發(fā)送數(shù)據(jù)到服務(wù)端   
            if("bye".equals(str)){  
                flag = false;  
            }else{  
                try{  
                    //從服務(wù)器端接收數(shù)據(jù)有個(gè)時(shí)間限制(系統(tǒng)自設(shè)颤诀,也可以自己設(shè)置)字旭,超過(guò)了這個(gè)時(shí)間,便會(huì)拋出該異常  
                    String echo = buf.readLine();  
                    System.out.println(echo);  
                }catch(SocketTimeoutException e){  
                    System.out.println("Time out, No response");  
                }  
            }  
        }  
        input.close();  
        if(client != null){  
            //如果構(gòu)造函數(shù)建立起了連接崖叫,則關(guān)閉套接字谐算,如果沒(méi)有建立起連接,自然不用關(guān)閉  
            client.close(); //只關(guān)閉socket归露,其關(guān)聯(lián)的輸入輸出流也會(huì)被關(guān)閉  
        }  
    }  
}

服務(wù)器端代碼
public class ThreadPoolServer {
    public static void main(String[] args) {
        ServerSocket server;
        ExecutorService executor=Executors.newFixedThreadPool(2);
        try {
            server = new ServerSocket(20012);
               Socket client = null;
                while(true){ 
                    System.out.println("服務(wù)器端等待客戶端發(fā)起連接請(qǐng)求");     
                    client = server.accept();
                    System.out.println("客戶端向服務(wù)器端發(fā)起了連接請(qǐng)求,且連接成功");
                    executor.execute(new Handler(client));                 
                }
        } catch (IOException e) {
            e.printStackTrace();
        }  
    }
}

線程處理代碼
public class Handler extends Thread{
    private Socket client; 
    PrintStream out;
    BufferedReader buf;
    public Handler(Socket client){
        this.client = client; 
        try {
            out = new PrintStream(client.getOutputStream());
            buf = new BufferedReader(new InputStreamReader(client.getInputStream())); 
            
        } catch (IOException e) {
            e.printStackTrace();
        }               
    } 
    public void run(){
         try{  
             boolean flag =true;  
             while(flag){                
                 String str =  buf.readLine();  
                 if(str == null || "".equals(str)){  
                     flag = false;  
                 }else{  
                     if("bye".equals(str)){  
                         flag = false;  
                     }else{  
                        System.out.println("服務(wù)器從客戶端接受到的數(shù)據(jù):"+str);
                         out.println("echo:" + str);  
                     }  
                 }  
             }  
             out.close();  
             client.close();  
         }catch(Exception e){  
             e.printStackTrace();  
         }  
     }      
}

此項(xiàng)目的完整代碼可以到我的github,java-socket進(jìn)行下載斤儿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剧包,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子往果,更是在濱河造成了極大的恐慌疆液,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陕贮,死亡現(xiàn)場(chǎng)離奇詭異堕油,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)肮之,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門掉缺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人戈擒,你說(shuō)我怎么就攤上這事眶明。” “怎么了筐高?”我有些...
    開(kāi)封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵搜囱,是天一觀的道長(zhǎng)丑瞧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蜀肘,這世上最難降的妖魔是什么绊汹? 我笑而不...
    開(kāi)封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮扮宠,結(jié)果婚禮上西乖,老公的妹妹穿的比我還像新娘。我一直安慰自己涵卵,他們只是感情好浴栽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著轿偎,像睡著了一般典鸡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坏晦,一...
    開(kāi)封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天萝玷,我揣著相機(jī)與錄音,去河邊找鬼昆婿。 笑死球碉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仓蛆。 我是一名探鬼主播睁冬,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼看疙!你這毒婦竟也來(lái)了豆拨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤能庆,失蹤者是張志新(化名)和其女友劉穎施禾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搁胆,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弥搞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渠旁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攀例。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖顾腊,靈堂內(nèi)的尸體忽然破棺而出肛度,到底是詐尸還是另有隱情,我是刑警寧澤投慈,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布承耿,位于F島的核電站冠骄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏加袋。R本人自食惡果不足惜凛辣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望职烧。 院中可真熱鬧扁誓,春花似錦、人聲如沸蚀之。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)足删。三九已至寿谴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間失受,已是汗流浹背讶泰。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拂到,地道東北人痪署。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像兄旬,于是被迫代替她去往敵國(guó)和親狼犯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在领铐,面了一些公司悯森,掛了不少,但最終還是拿到小米罐孝、百度、阿里肥缔、京東莲兢、新浪、CVTE续膳、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,186評(píng)論 11 349
  • java socket系列文章java socket 單線程echo服務(wù)器java socket 多線程ech...
    snoweek閱讀 2,033評(píng)論 1 9
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理改艇,服務(wù)發(fā)現(xiàn),斷路器坟岔,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 早上谒兄,一一問(wèn)候了幾位我的VlP客戶。作為服務(wù)人員社付,我們不能等著客戶來(lái)找我們承疲,而是要經(jīng)常的去關(guān)心他們的工作邻耕,生活。...
    孫其花閱讀 514評(píng)論 7 0
  • 小時(shí)候燕鸽,覺(jué)得時(shí)間是一只透明的蝴蝶兄世! 長(zhǎng)大后,時(shí)間變成了一只凝視著你的黑貓啊研!
    陳魯方閱讀 95評(píng)論 0 0