系統啟動一個新線程的成本是比較高的,因為它涉及與操作系統交互。在這種情形下,使用線程池可以很好的提高性能,尤其是當程序需要創建大量生存周期很短的線程時,更應該考慮使用線程池。
與數據庫連接池類似的是,線程池在系統啟動的時候創建大量空閑的線程,程序將一個Runnable對象傳給線程池,線程池就會啟動一條線程來執行該對象的run方法,當run方法執行結束后,該線程并不會死亡,而是再次返回線程池中成為空閑狀態,等待下一個Runnable對象的run方法。
除此之外,使用線程池可以有效控制系統中并發線程的數量,但系統中包含大量并發線程時,會導致系統性能急劇下降,而線程池的最大線程數量可以控制系統中并發線程的數目不超過此數目。 在jdk1.5以前,開發者必須手動實現自己的線程池,從jdk1.5開始,java內建支持線程池。
相關類介紹:
1. java.util.concurrent.Executors:此類是一個工廠類,提供了生成線程池的方法,主要提供了以下幾個靜態方法來生成各種線程池。
l newCachedThreadPool():創建一個具有緩存功能的線程池,系統根據需要創建線程,這些線程將被緩存。
l newFixedThreadPool(int nThreads);創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程,在需要時使用提供的 ThreadFactory 創建新線程。
l newSingleThreadExecutor();創建只有一個單線程的線程池,相當于newFixedThreadPool()傳入的參數為1.
l newScheduledThreadPool();創建一個線程池,它可安排在給定延遲后運行命令或者定期地執行。
前面三個方法都返回ExecutorService對象,該對象代表一個線程池,它可以執行Runnable對象或者Callable對象所代表的線程。而最后一個方法返回一個ScheduledExecutorService線程池,它是ExecutorService的子類,它可以在指定延遲后執行線程任務。
2. java.util.concurrent.ExecutorService: ExecutorService代表盡快執行線程池中的線程(只要線程池中有空閑的線程立即執行線程任務),程序只要將一個Runable對象或Callable對象提交給該線程池即可,該線程會盡快執行該任務。此類提供了三個方法:
l <T> Future<T>submit(Callable<T> task) :提交一個返回值的任務用于執行,返回一個表示任務的未決結果的 Future。
l Future<?> submit(Runnable task) :提交一個 Runnable 任務用于執行,并返回一個表示該任務的 Future。
l <T> Future<T> submit(Runnable task, T result) :提交一個 Runnable 任務用于執行,并返回一個表示該任務的 Future。
3. java.util.concurrent.ScheduledExecutorService:此類代表可在指定延遲或周期行執行線程任務的線程池,它提供了如下四個方法:
l <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) :創建并執行在給定延遲后啟用的 ScheduledFuture。
l ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) : 創建并執行在給定延遲后啟用的一次性操作。
l ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) :創建并執行一個在給定初始延遲后首次啟用的定期操作,后續操作具有給定的周期;也就是將在 initialDelay 后開始執行,然后在 initialDelay+period 后執行,接著在 initialDelay + 2 * period 后執行,依此類推。
l ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) :創建并執行一個在給定初始延遲后首次啟用的定期操作,隨后,在每一次執行終止和下一次執行開始之間都存在給定的延遲。
當線程池用完以后,應該調用該線程池的shutdown方法,該方法將關閉線程池,調用了shurdown后的線程池將不再接受新的任務,但將會以前所有已經提交的任務執行完成。當線程池中所有的任務都執行完成后,線程池中的所有線程都會死亡;另外也可以調用線程池的shutdownNow方法來關閉線程池,該方法試圖停止所有正在執行的活動任務。
使用線程池的步驟如下:
1. 調用Executors類的靜態工廠方法創建一個ExecutorService對象,該對象代表一個線程池。
2. 創建Runable實現類或Callable實現類的實例,作為線程執行任務。
3. 調用ExecutorService對象的submit方法來提交Runnable或Callable實例。
4. 當不想提交任何任務時調用shutdown方法來關閉線程池。
下面是一個簡單的例子,客戶端發送消息,服務器端接受消息,并輸出。
Server:
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("服務器啟動。。。");
}
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;