java网络编程(5)

来源:互联网 发布:高铁外交 知乎 编辑:程序博客网 时间:2024/05/18 02:05

 基于线程池的socket服务器

 

/**
 * 
 
*/

package et.bo.sun._3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
@author zhangfeng
 * 
 
*/

public class EchoServerPool {

    
private int port = 8000;

    
private ServerSocket serverSocket;

    
private ExecutorService executorService;// 线程池

    
private final int POOL_SIZE = 4;// 每个CPU在线程池中工作线程的数目

    
public EchoServerPool() throws IOException {
        serverSocket 
= new ServerSocket(port);
        
// executorService = new
        
// ThreadPool(Runtime.getRuntime().availableProcessors()
        
// * POOL_SIZE);
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
                .availableProcessors()
                
* POOL_SIZE);
        System.out.println(
"服务器启动");
    }


    
public void service() {
        
while (true{
            Socket socket 
= null;
            
try {
                socket 
= serverSocket.accept();
                
// Thread workThread = new Thread(new Handler(socket));
                
// workThread.start();
                executorService.execute(new Handler(socket));
            }
 catch (Exception e) {
                
// TODO: handle exception
                e.printStackTrace();
            }

        }

    }


    
// 每来一个请求就启动一个线程,与客户端通信
    class Handler implements Runnable {
        
private Socket socket;

        
public Handler(Socket socket) {
            
this.socket = socket;
        }


        
// 输出流,发送信息
        private PrintWriter getWriter(Socket socket) throws IOException {
            OutputStream socketOut 
= socket.getOutputStream();
            
return new PrintWriter(socketOut, true);
        }


        
// 输入流,接收信息
        private BufferedReader getReader(Socket socket) throws IOException {
            InputStream socketIn 
= socket.getInputStream();
            
return new BufferedReader(new InputStreamReader(socketIn));
        }


        
public String echo(String msg) {
            
return "echo" + msg;
        }


        
public void run() {
            
try {
                
// 得到远端连接ip和端口
                System.out.println("有新的连接.." + socket.getInetAddress() + ":"
                        
+ socket.getPort());
                
// 打开通道
                BufferedReader br = getReader(socket);
                PrintWriter pw 
= getWriter(socket);

                String msg 
= null;
                
while ((msg = br.readLine()) != null{
                    System.out.println(msg);
                    pw.println(echo(msg));
                    
if (msg.equals("bye")) {
                        
break;
                    }

                }

            }
 catch (Exception e) {
                
// TODO: handle exception
                e.printStackTrace();
            }
 finally {
                
try {
                    
if (socket != null{
                        socket.close();
                    }

                }
 catch (Exception e) {
                    
// TODO: handle exception
                    e.printStackTrace();
                }

            }

        }

    }


    
public static void main(String[] args) throws IOException {
        
new EchoServerPool().service();// 启动服务器
    }


}

 

使用线程池有如下问题
1)死锁
线程A持有对象C的锁,而等待对象D的锁,线程B持有对象D的锁,而等待对象C的锁,双方都不释放,这样死锁就产生了。
2)系统资源
3)线程丢失
异常导致线程永远不能回到线程池中。
4)任务量过大,线程池中的线程不能满足消耗导致。