同步阻塞模式
利用长轮询实现持续监听,利用socketserver.accept()进行阻塞。
在一个由volatile变量控制的while循环中,不断尝试serversocket.accept()方法,当没有socket进行连接时,程序会阻塞在该方法>上,当有socket连接时,则获得这个socket,传递给工作线程池,并继续等待。这种方式在处理高并发情况下会创建过多的socket连接,导致消耗大量内存。
服务端代码
public class ServerStarterextends Thread {
private static volatile boolean flag =true;
private ServerSocketserverSocket =null;
private ExecutorServiceserverThreadPool;
ServerStarter( int port) {
ThreadFactory threadFactory =new ThreadFactoryBuilder()
.setNameFormat("server-pool-%d").build();
serverThreadPool =new ThreadPoolExecutor(10, 10,
1000, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1024), threadFactory, new ThreadPoolExecutor.AbortPolicy());
try {
serverSocket =new ServerSocket(port);
}catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (flag) {
try {
Socket sock =serverSocket.accept();
SocketTask s =new SocketTask(sock);
serverThreadPool.submit(s);
}catch (IOException e) {
System.out.println("system shutdown");
}
}
}
在创建线程池时,推荐使用阿里编程规约中推荐的利用线程池构造器来进行构造,这种方式可以对线程池的线程进行命名,便于日后的调试与维护。
这里这我们创建了一个线程池来独立处理每一个socket连接,从而实现了对多客户端同时访问的支持,下面是任务线程类示范
public void client() {
try {
Socket socket = new Socket(serverhost, serverport);
dojob();
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write(msg);
writer.newLine();
writer.flush();
try {
/**获取一个输入流,接收服务端的信息*/
InputStream inputStream = socket.getInputStream();
/**包装成字符流,提高效率*/
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
/**缓冲区*/
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String t = bufferedReader.readLine();
dosomething();
} catch (Exception e) {
System.out.println("server send wrong data");
}
socket.close();
} catch (UnknownHostException e) {
System.out.println("host not found");
} catch (IOException e) {
System.out.println("server holding");
}
}
网友评论