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中直接賦值
PrintWriter writer=null在try中直接賦值那麼它的生命周期就只是在try語句塊中