public class Server {
//服务端socket
private ServerSocket serverSocket;
//所有客户输出流
private List allOut;
//线程池
private ExecutorService threadPool;
/**
* 构造方法,用于初始化
*
/
public Server() {
try{
serverSocket=new ServerSocket(8088);
allOut=new ArrayList();
threadPool=Executors.newFixedThreadPool(40);
}catch(Exception e){
e.printStackTrace();
}
}
/*
* 服务端开启方法
*/
public void start(){
while(true){
try{
System.out.println("等待服务端连接!");
//监听客户端连接
Socket socket=serverSocket.accept();
System.out.println("服务端已经连接");
//启动一个线程来完成针对客户端的操作
ClientHandler handler=new ClientHandler(socket);
threadPool.execute(handler);
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 将输出流存入共享集合,与下面两个方法互斥 保证同步安全
* @param out
*/
public synchronized void addOut(PrintWriter out){
allOut.add(out);
}
/**
* 将输出流从共享集合删除
* @param out
*/
public synchronized void removeOut(PrintWriter out){
allOut.remove(out);
}
/**
* 将信息转发给所有客户端
*/
public synchronized void sendMessage(String message){
for(PrintWriter o:allOut){
o.println(message);
}
}
public static void main(String[] args) {
Server server=new Server();
server.start();
}
/**
* 线程体,用于处理不同客户端的交互
* @author Long
*
*/
private class ClientHandler implements Runnable{
private Socket socket;
//该线程用于处理客户端
public ClientHandler(Socket socket){
this.socket=socket;
}
@Override
public void run(){
PrintWriter writer=null;
try{
//获取客户端输出流存入共享集合,广播消息
OutputStream os=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(os,"utf-8");
writer=new PrintWriter(osw,true);
/**
* 将用户发的信息存入共享集合,需要同步
*/
addOut(writer);
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is, "utf-8");
BufferedReader reader=new BufferedReader(isr);
Scanner sc=new Scanner(System.in);
String message=null;
while((message=reader.readLine())!=null){
sendMessage(message);
}
}catch(Exception e){
e.printStackTrace();
}finally{
/**
* 当客户端断线,要将输出流从共享集合中移除
* 需要同步
*/
removeOut(writer);
if(socket!=null){
try{
socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
}
1. 在线程体中(文中黑线)为什么要先PrintWriter writer=null而不是在try中直接赋值