Java Thread Pool
系統(tǒng)啟動(dòng)一個(gè)新線程的成本是比較高的,因?yàn)樗婕芭c操作系統(tǒng)交互。在這種情形下,使用線程池可以很好的提高性能,尤其是當(dāng)程序需要?jiǎng)?chuàng)建大量生存周期很短的線程時(shí),更應(yīng)該考慮使用線程池。
與數(shù)據(jù)庫(kù)連接池類似的是,線程池在系統(tǒng)啟動(dòng)的時(shí)候創(chuàng)建大量空閑的線程,程序?qū)⒁粋€(gè)Runnable對(duì)象傳給線程池,線程池就會(huì)啟動(dòng)一條線程來(lái)執(zhí)行該對(duì)象的run方法,當(dāng)run方法執(zhí)行結(jié)束后,該線程并不會(huì)死亡,而是再次返回線程池中成為空閑狀態(tài),等待下一個(gè)Runnable對(duì)象的run方法。
除此之外,使用線程池可以有效控制系統(tǒng)中并發(fā)線程的數(shù)量,但系統(tǒng)中包含大量并發(fā)線程時(shí),會(huì)導(dǎo)致系統(tǒng)性能急劇下降,而線程池的最大線程數(shù)量可以控制系統(tǒng)中并發(fā)線程的數(shù)目不超過(guò)此數(shù)目。 在jdk1.5以前,開(kāi)發(fā)者必須手動(dòng)實(shí)現(xiàn)自己的線程池,從jdk1.5開(kāi)始,java內(nèi)建支持線程池。
相關(guān)類介紹:
1. java.util.concurrent.Executors:此類是一個(gè)工廠類,提供了生成線程池的方法,主要提供了以下幾個(gè)靜態(tài)方法來(lái)生成各種線程池。
l newCachedThreadPool():創(chuàng)建一個(gè)具有緩存功能的線程池,系統(tǒng)根據(jù)需要?jiǎng)?chuàng)建線程,這些線程將被緩存。
l newFixedThreadPool(int nThreads);創(chuàng)建一個(gè)可重用固定線程數(shù)的線程池,以共享的無(wú)界隊(duì)列方式來(lái)運(yùn)行這些線程,在需要時(shí)使用提供的 ThreadFactory 創(chuàng)建新線程。
l newSingleThreadExecutor();創(chuàng)建只有一個(gè)單線程的線程池,相當(dāng)于newFixedThreadPool()傳入的參數(shù)為1.
l newScheduledThreadPool();創(chuàng)建一個(gè)線程池,它可安排在給定延遲后運(yùn)行命令或者定期地執(zhí)行。
前面三個(gè)方法都返回ExecutorService對(duì)象,該對(duì)象代表一個(gè)線程池,它可以執(zhí)行Runnable對(duì)象或者Callable對(duì)象所代表的線程。而最后一個(gè)方法返回一個(gè)ScheduledExecutorService線程池,它是ExecutorService的子類,它可以在指定延遲后執(zhí)行線程任務(wù)。
2. java.util.concurrent.ExecutorService: ExecutorService代表盡快執(zhí)行線程池中的線程(只要線程池中有空閑的線程立即執(zhí)行線程任務(wù)),程序只要將一個(gè)Runable對(duì)象或Callable對(duì)象提交給該線程池即可,該線程會(huì)盡快執(zhí)行該任務(wù)。此類提供了三個(gè)方法:
l <T> Future<T>submit(Callable<T> task) :提交一個(gè)返回值的任務(wù)用于執(zhí)行,返回一個(gè)表示任務(wù)的未決結(jié)果的 Future。
l Future<?> submit(Runnable task) :提交一個(gè) Runnable 任務(wù)用于執(zhí)行,并返回一個(gè)表示該任務(wù)的 Future。
l <T> Future<T> submit(Runnable task, T result) :提交一個(gè) Runnable 任務(wù)用于執(zhí)行,并返回一個(gè)表示該任務(wù)的 Future。
3. java.util.concurrent.ScheduledExecutorService:此類代表可在指定延遲或周期行執(zhí)行線程任務(wù)的線程池,它提供了如下四個(gè)方法:
l <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) :創(chuàng)建并執(zhí)行在給定延遲后啟用的 ScheduledFuture。
l ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) : 創(chuàng)建并執(zhí)行在給定延遲后啟用的一次性操作。
l ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) :創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,后續(xù)操作具有給定的周期;也就是將在 initialDelay 后開(kāi)始執(zhí)行,然后在 initialDelay+period 后執(zhí)行,接著在 initialDelay + 2 * period 后執(zhí)行,依此類推。
l ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) :創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,隨后,在每一次執(zhí)行終止和下一次執(zhí)行開(kāi)始之間都存在給定的延遲。
當(dāng)線程池用完以后,應(yīng)該調(diào)用該線程池的shutdown方法,該方法將關(guān)閉線程池,調(diào)用了shurdown后的線程池將不再接受新的任務(wù),但將會(huì)以前所有已經(jīng)提交的任務(wù)執(zhí)行完成。當(dāng)線程池中所有的任務(wù)都執(zhí)行完成后,線程池中的所有線程都會(huì)死亡;另外也可以調(diào)用線程池的shutdownNow方法來(lái)關(guān)閉線程池,該方法試圖停止所有正在執(zhí)行的活動(dòng)任務(wù)。
使用線程池的步驟如下:
1. 調(diào)用Executors類的靜態(tài)工廠方法創(chuàng)建一個(gè)ExecutorService對(duì)象,該對(duì)象代表一個(gè)線程池。
2. 創(chuàng)建Runable實(shí)現(xiàn)類或Callable實(shí)現(xiàn)類的實(shí)例,作為線程執(zhí)行任務(wù)。
3. 調(diào)用ExecutorService對(duì)象的submit方法來(lái)提交Runnable或Callable實(shí)例。
4. 當(dāng)不想提交任何任務(wù)時(shí)調(diào)用shutdown方法來(lái)關(guān)閉線程池。
下面是一個(gè)簡(jiǎn)單的例子,客戶端發(fā)送消息,服務(wù)器端接受消息,并輸出。
package com.hs.threadpool;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author jianggy
*
*/
public class Server {
private int port=21245;
private ServerSocket ss;
public Server() throws IOException{
ss = new ServerSocket(port);
System.out.println("服務(wù)器啟動(dòng)。。。");
}
public void serverService(){
ExecutorService es = Executors.newFixedThreadPool(5);
while(true){
Socket socket = null;
try {
socket = ss.accept();
es.execute(new ServerHandler(socket));
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException{
Server server = new Server();
server.serverService();
}
}
package com.hs.threadpool;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class ServerHandler implements Runnable {
private Socket socket;
private InputStream in;
public ServerHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
char[] chars = new char[100];
StringBuffer sb = new StringBuffer();
try {
in = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
while(reader.read(chars)!=-1){
sb.append(chars);
}
System.out.println(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client:
package com.hs.threadpool;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class Client {
private static int port = 21245;
private static String ip = "192.168.231.166";
private SocketChannel sc;
private ByteBuffer bb = ByteBuffer.allocate(1024);
public void connectToServer() throws IOException {
try {
sc = SocketChannel.open();
InetSocketAddress add = new InetSocketAddress(ip,port);
sc.connect(add);
while(!sc.finishConnect()){
System.out.println("waitting connect to server。。。。。。");
Thread.sleep(100);
}
Thread.sleep(10000);
bb = ByteBuffer.wrap("abcdefg".getBytes());
sc.write(bb);
bb.clear();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if(sc!=null&&sc.isConnected()){
sc.close();
System.out.println("connetion is closed


}
}
}
public static void main(String[] args) throws IOException{
Client c = new Client();
c.connectToServer();
}
}
-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;
posted on 2012-06-04 03:58 Chan Chen 閱讀(1598) 評(píng)論(0) 編輯 收藏 所屬分類: Scala / Java