JAVA怎么实现自动关闭服务器
今天小编给大家分享一下JAVA怎么实现自动关闭服务器的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
普通实现的服务器都无法关闭自身,只有依靠操作系统来强行终止服务程序。这种强行终止服务程序的方式尽管简单方便,但会导致服务器中正在执行的任务突然中断。如果服务器处理的任务非常重要,不允许被突然中断,应该由服务器自身在恰当的时刻关闭自己
代码如下:
EchoServer类
packageShutdownServer;importjava.io.*;importjava.net.ServerSocket;importjava.net.Socket;importjava.net.SocketException;importjava.net.SocketTimeoutException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.RejectedExecutionException;importjava.util.concurrent.TimeUnit;publicclassEchoServer{privateintport=8000;privateServerSocketserverSocket;privateExecutorServiceexecutorService;//线程池privatefinalintPOOL_SIZE=4;//单个CPU时线程池中工作线程的数目privateintportForShutdown=8001;//用于监听关闭服务器命令的端口privateServerSocketserverSocketShutdown;privatebooleanisShutdown=false;//服务器是否已经关闭privateThreadshutdownThread=newThread(){//负责关闭服务器的线程publicvoidrun(){while(!isShutdown){SocketsocketForShutdown=null;try{socketForShutdown=serverSocketShutdown.accept();BufferedReaderbr=newBufferedReader(newInputStreamReader(socketForShutdown.getInputStream()));Stringcommand=br.readLine();if(command.equals("shutdown")){longbeginTime=System.currentTimeMillis();socketForShutdown.getOutputStream().write("服务器正在关闭\r\n".getBytes());isShutdown=true;//请求关闭线程池//线程池不再接收新的任务,但会继续执行完工作队列中现有的任务executorService.shutdown();//等待关闭线程池,每次等待的超时时间为30s//当使用awaitTermination时,主线程会处于一种等待的状态,等待线程池中所有的线程都运行完毕后才继续运行。//如果等待的时间超过指定的时间,但是线程池中的线程运行完毕,那么awaitTermination()返回true。执行分线程已结束//如果等待的时间超过指定的时间,但是线程池中的线程未运行完毕,那么awaitTermination()返回false。不执行分线程已结束//如果等待时间没有超过指定时间,等待!//可以用awaitTermination()方法来判断线程池中是否有继续运行的线程。while(!executorService.isTerminated())executorService.awaitTermination(30,TimeUnit.SECONDS);//关闭与EchoClient客户通信的ServerSocketserverSocket.close();longendTime=System.currentTimeMillis();socketForShutdown.getOutputStream().write(("服务器关闭,"+"关闭服务器用了"+(endTime-beginTime)+"ms\r\n").getBytes());socketForShutdown.close();serverSocketShutdown.close();System.out.println("服务器关闭");}else{socketForShutdown.getOutputStream().write("错误的命令\r\n".getBytes());socketForShutdown.close();}}catch(Exceptione){e.printStackTrace();}}}};publicEchoServer()throwsIOException{serverSocket=newServerSocket(port);//设定等待客户连接的超时时间为60sserverSocket.setSoTimeout(60000);serverSocketShutdown=newServerSocket(portForShutdown);//创建线程池executorService=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);shutdownThread.start();System.out.println("服务器启动");}publicvoidservice(){while(!isShutdown){Socketsocket=null;try{//可能会抛出SocketTimeoutException和SocketExceptionsocket=serverSocket.accept();//把等待客户发送数据的超时时间设为60ssocket.setSoTimeout(60000);//可能会抛出RejectedExecutionExceptionexecutorService.execute(newHandler(socket));}catch(SocketTimeoutExceptione){//不必处理等待客户连接时出现的异常}catch(RejectedExecutionExceptione){try{if(socket!=null)socket.close();}catch(IOExceptionex){return;}}catch(SocketExceptione){if(e.getMessage().indexOf("socketclosed")!=-1)return;}catch(IOExceptione){e.printStackTrace();}}}publicstaticvoidmain(String[]args)throwsIOException{//main方法抛出异常,异常直接交给虚拟机,虚拟机直接结束异常newEchoServer().service();}}//负责与单个客户通信的任务classHandlerimplementsRunnable{privateSocketsocket;publicHandler(Socketsocket){this.socket=socket;}privatePrintWritergetWriter(Socketsocket)throwsIOException{OutputStreamsocketOut=socket.getOutputStream();returnnewPrintWriter(socketOut,true);}privateBufferedReadergetReader(Socketsocket)throwsIOException{InputStreamsocketIn=socket.getInputStream();returnnewBufferedReader(newInputStreamReader(socketIn));}publicStringecho(Stringmsg){return"echo:"+msg;}@Overridepublicvoidrun(){try{System.out.println("Newconnectionaccepted"+socket.getInetAddress()+":"+socket.getPort());BufferedReaderbr=getReader(socket);PrintWriterpw=getWriter(socket);Stringmsg=null;//接收和发送数据,直到通信结束while((msg=br.readLine())!=null){System.out.println("from"+socket.getInetAddress()+":"+socket.getPort()+">"+msg);pw.println(echo(msg));if(msg.equals("bye"))break;}}catch(IOExceptione){e.printStackTrace();}finally{try{if(socket!=null)socket.close();}catch(IOExceptione){e.printStackTrace();}}}}
AdminClient类(负责向EchoServer发送“shutdown”命令,关闭服务器)
packageShutdownServer;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputStream;importjava.net.Socket;publicclassAdminClient{publicstaticvoidmain(String[]args){Socketsocket=null;try{socket=newSocket("localhost",8001);//发送关闭命令OutputStreamsocketOut=socket.getOutputStream();//Scannerscanner=newScanner(System.in);//Stringorder=scanner.next();socketOut.write("shutdown\r\n".getBytes());//接收服务器反馈BufferedReaderbr=newBufferedReader(newInputStreamReader(socket.getInputStream()));Stringmsg=null;while((msg=br.readLine())!=null){System.out.println(msg);}}catch(Exceptione){e.printStackTrace();}finally{try{if(socket!=null)socket.close();}catch(IOExceptione){e.printStackTrace();}}}}
Client类(客户,与服务器进行通讯)
packageShutdownServer;importjava.io.*;importjava.net.Socket;publicclassClient{privateStringhost="localhost";privateintport=8000;privateSocketsocket;publicClient()throwsIOException{socket=newSocket(host,port);}privatePrintWritergetWriter(Socketsocket)throwsIOException{OutputStreamsocketOut=socket.getOutputStream();returnnewPrintWriter(socketOut,true);}privateBufferedReadergetReader(Socketsocket)throwsIOException{InputStreamsocketIn=socket.getInputStream();returnnewBufferedReader(newInputStreamReader(socketIn));}publicvoidtalk()throwsIOException{try{BufferedReaderbr=getReader(socket);PrintWriterpw=getWriter(socket);BufferedReaderlocalReader=newBufferedReader(newInputStreamReader(System.in));Stringmsg=null;while((msg=localReader.readLine())!=null){pw.println(msg);System.out.println(br.readLine());if(msg.equals("bye")){break;}}}catch(IOExceptione){e.printStackTrace();}finally{try{socket.close();}catch(IOExceptione){e.printStackTrace();}}}publicstaticvoidmain(Stringargs[])throwsIOException{newClient().talk();}}
shutdownThread线程负责关闭服务器,它一直监听8001端口,如果接收到了AdminClient发送的“shutdown”命令,就把isShutdown设置为true。
在关闭服务器时,我们使用了最常用的方法,先调用线程池的shutdown()方法,接着调用线程池的awaitTermination()方法。
executorService.shutdown();//等待关闭线程池,每次等待的超时时间为30s//当使用awaitTermination时,主线程会处于一种等待的状态,等待线程池中所有的线程都运行完毕后才继续运行。//如果等待的时间超过指定的时间,但是线程池中的线程运行完毕,那么awaitTermination()返回true。执行分线程已结束//如果等待的时间超过指定的时间,但是线程池中的线程未运行完毕,那么awaitTermination()返回false。不执行分线程已结束//如果等待时间没有超过指定时间,等待!//可以用awaitTermination()方法来判断线程池中是否有继续运行的线程。while(!executorService.isTerminated())executorService.awaitTermination(30,TimeUnit.SECONDS);
在线程池执行了shutdown()方法后,线程池不会在接收新的任务,同时该线程因为调用awaitTermination()方法而发生阻塞,直到线程池中所有线程的任务执行完毕,该线程才会继续向下
运行结果先运行EchoServer,Client,AdminClient后,再开启一客户程序Client1,显示Client1无法被加入线程池
EchoServer(只显示连接了Client,未连接Client1)
Client
Client2(向服务器发送消息,收到null)
AdminClient(在Client没有运行结束时,被阻塞)
当Client输入“bye”结束运行后,AdminClient关闭服务器
Client类
EchoServer类
AdminClient类
以上就是“JAVA怎么实现自动关闭服务器”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。