欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

教你利用JAVA實現(xiàn)可以自行關閉服務器的方法

 更新時間:2021年06月29日 15:32:20   作者:徐徐大嫂  
今天給大家?guī)淼氖顷P于Java的相關知識,文章圍繞著利用JAVA實現(xiàn)可以自行關閉服務器的方法展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下

JAVA實現(xiàn)可以自行關閉的服務器

普通實現(xiàn)的服務器都無法關閉自身,只有依靠操作系統(tǒng)來強行終止服務程序。這種強行終止服務程序的方式盡管簡單方便,但會導致服務器中正在執(zhí)行的任務突然中斷。如果服務器處理的任務非常重要,不允許被突然中斷,應該由服務器自身在恰當的時刻關閉自己

代碼如下:

  • EchoServer類
package ShutdownServer;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

public class EchoServer {
    private int port=8000;
    private ServerSocket serverSocket;
    private ExecutorService executorService; //線程池
    private final int POOL_SIZE=4; //單個CPU時線程池中工作線程的數目

    private int portForShutdown=8001; //用于監(jiān)聽關閉服務器命令的端口
    private ServerSocket serverSocketShutdown;
    private boolean isShutdown=false; //服務器是否已經關閉

    private Thread shutdownThread=new Thread(){
        //負責關閉服務器的線程
        public void run(){
            while(!isShutdown){
                Socket socketForShutdown=null;
                try{
                    socketForShutdown=serverSocketShutdown.accept();
                    BufferedReader br=new BufferedReader(
                            new InputStreamReader(socketForShutdown.getInputStream())
                    );
                    String command=br.readLine();
                    if (command.equals("shutdown")){
                        long beginTime=System.currentTimeMillis();
                        socketForShutdown.getOutputStream().write("服務器正在關閉\r\n".getBytes());
                        isShutdown=true;

                        //請求關閉線程池
                        //線程池不再接收新的任務,但會繼續(xù)執(zhí)行完工作隊列中現(xiàn)有的任務
                        executorService.shutdown();

                        //等待關閉線程池,每次等待的超時時間為30s
                        //當使用awaitTermination時,主線程會處于一種等待的狀態(tài),等待線程池中所有的線程都運行完畢后才繼續(xù)運行。
                        //如果等待的時間超過指定的時間,但是線程池中的線程運行完畢,那么awaitTermination()返回true。執(zhí)行分線程已結束
                        //如果等待的時間超過指定的時間,但是線程池中的線程未運行完畢,那么awaitTermination()返回false。不執(zhí)行分線程已結束
                        //如果等待時間沒有超過指定時間,等待!
                        //可以用awaitTermination()方法來判斷線程池中是否有繼續(xù)運行的線程。
                        while(!executorService.isTerminated())
                            executorService.awaitTermination(30, TimeUnit.SECONDS);
                            //關閉與EchoClient客戶通信的ServerSocket
                            serverSocket.close();
                            long endTime=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 (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    public EchoServer() throws IOException {
        serverSocket=new ServerSocket(port);
        //設定等待客戶連接的超時時間為60s
        serverSocket.setSoTimeout(60000);
        serverSocketShutdown=new ServerSocket(portForShutdown);

        //創(chuàng)建線程池
        executorService= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
        shutdownThread.start();
        System.out.println("服務器啟動");
    }

    public void service(){
        while(!isShutdown){
            Socket socket=null;
            try {
                //可能會拋出SocketTimeoutException和SocketException
                socket=serverSocket.accept();
                //把等待客戶發(fā)送數據的超時時間設為60s
                socket.setSoTimeout(60000);
                //可能會拋出RejectedExecutionException
                executorService.execute(new Handler(socket));
            }catch (SocketTimeoutException e){
                //不必處理等待客戶連接時出現(xiàn)的異常
            }catch (RejectedExecutionException e) {
                try {
                    if (socket != null)
                        socket.close();
                } catch (IOException ex) {
                    return;
                }
            }catch (SocketException e){
                if (e.getMessage().indexOf("socket closed")!=-1)
                    return;
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException { //main方法拋出異常,異常直接交給虛擬機,虛擬機直接結束異常
        new EchoServer().service();
    }
}

//負責與單個客戶通信的任務
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;
    }

    @Override
    public void run() {
        try{
            System.out.println("New connection accepted "+socket.getInetAddress()+":"+socket.getPort());
            BufferedReader br=getReader(socket);
            PrintWriter pw=getWriter(socket);

            String msg=null;
            //接收和發(fā)送數據,直到通信結束
            while((msg=br.readLine())!=null){
                System.out.println("from "+socket.getInetAddress()+":"+socket.getPort()+">"+msg);
                pw.println(echo(msg));
                if (msg.equals("bye"))
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try{
                if (socket!=null)
                    socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}
  • AdminClient類(負責向EchoServer發(fā)送“shutdown”命令,關閉服務器)
package ShutdownServer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class AdminClient {
    public static void main(String[] args){
        Socket socket=null;
        try{
            socket=new Socket("localhost",8001);
            //發(fā)送關閉命令
            OutputStream socketOut=socket.getOutputStream();
            //Scanner scanner=new Scanner(System.in);
            //String order=scanner.next();
            socketOut.write("shutdown\r\n".getBytes());
            //接收服務器反饋
            BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String msg=null;
            while ((msg=br.readLine())!=null){
                System.out.println(msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try{
                if (socket!=null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • Client類(客戶,與服務器進行通訊)
package ShutdownServer;

import java.io.*;
import java.net.Socket;

public class Client {
    private String host="localhost";
    private int port=8000;
    private Socket socket;

    public Client() throws IOException {
        socket=new Socket(host,port);
    }

    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 void talk() throws IOException{
        try{
            BufferedReader br=getReader(socket);
            PrintWriter pw=getWriter(socket);
            BufferedReader localReader=new BufferedReader(new InputStreamReader(System.in));
            String msg=null;
            while((msg=localReader.readLine()) != null){
                pw.println(msg);
                System.out.println(br.readLine());

                if (msg.equals("bye")){
                    break;
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        finally {
            try{
                socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]) throws IOException {
        new Client().talk();
    }
}

shutdownThread線程負責關閉服務器,它一直監(jiān)聽8001端口,如果接收到了AdminClient發(fā)送的“shutdown”命令,就把isShutdown設置為true。

在關閉服務器時,我們使用了最常用的方法,先調用線程池的shutdown()方法,接著調用線程池的awaitTermination()方法。

executorService.shutdown();

                        //等待關閉線程池,每次等待的超時時間為30s
                        //當使用awaitTermination時,主線程會處于一種等待的狀態(tài),等待線程池中所有的線程都運行完畢后才繼續(xù)運行。
                        //如果等待的時間超過指定的時間,但是線程池中的線程運行完畢,那么awaitTermination()返回true。執(zhí)行分線程已結束
                        //如果等待的時間超過指定的時間,但是線程池中的線程未運行完畢,那么awaitTermination()返回false。不執(zhí)行分線程已結束
                        //如果等待時間沒有超過指定時間,等待!
                        //可以用awaitTermination()方法來判斷線程池中是否有繼續(xù)運行的線程。
                        while(!executorService.isTerminated())
                            executorService.awaitTermination(30, TimeUnit.SECONDS);

在線程池執(zhí)行了shutdown()方法后,線程池不會在接收新的任務,同時該線程因為調用awaitTermination()方法而發(fā)生阻塞,直到線程池中所有線程的任務執(zhí)行完畢,該線程才會繼續(xù)向下

運行結果

先運行EchoServer,Client,AdminClient后,再開啟一客戶程序Client1,顯示Client1無法被加入線程池

  • EchoServer(只顯示連接了Client,未連接Client1)

在這里插入圖片描述

  • Client

在這里插入圖片描述

  • Client2(向服務器發(fā)送消息,收到null)

在這里插入圖片描述

  • AdminClient(在Client沒有運行結束時,被阻塞)

在這里插入圖片描述

當Client輸入“bye”結束運行后,AdminClient關閉服務器

  • Client類

在這里插入圖片描述

  • EchoServer類

在這里插入圖片描述

  • AdminClient類

在這里插入圖片描述

參考Java網絡編程核心技術詳解

到此這篇關于教你利用JAVA實現(xiàn)可以自行關閉服務器的方法的文章就介紹到這了,更多相關JAVA自行關閉服務器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java實現(xiàn)PPT轉化為PDF

    java實現(xiàn)PPT轉化為PDF

    這篇文章主要為大家詳細介紹了java實現(xiàn)PPT轉化為PDF的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 解析HikariCP一百行代碼輕松掌握多線程

    解析HikariCP一百行代碼輕松掌握多線程

    這篇文章主要為大家介紹了HikariCP一百行代碼解析,輕松掌握多線程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 使用ObjectMapper解析json不用一直new了

    使用ObjectMapper解析json不用一直new了

    這篇文章主要為大家介紹了使用ObjectMapper解析json不用一直new了的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • JAVA面試題 簡談你對synchronized關鍵字的理解

    JAVA面試題 簡談你對synchronized關鍵字的理解

    這篇文章主要介紹了JAVA面試題 請談談你對Sychronized關鍵字的理解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • 關于@PostConstruct、afterPropertiesSet和init-method的執(zhí)行順序

    關于@PostConstruct、afterPropertiesSet和init-method的執(zhí)行順序

    這篇文章主要介紹了關于@PostConstruct、afterPropertiesSet和init-method的執(zhí)行順序,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java?IDEA集成開發(fā)工具中英文切換圖文教程

    Java?IDEA集成開發(fā)工具中英文切換圖文教程

    相信很多小伙伴們剛接觸IDEA時,看到一堆英文界面不知道如何下手,這篇文章主要給大家介紹了關于Java?IDEA集成開發(fā)工具中英文切換的相關資料,需要的朋友可以參考下
    2024-04-04
  • Spring?Cloud?OAuth2實現(xiàn)自定義token返回格式

    Spring?Cloud?OAuth2實現(xiàn)自定義token返回格式

    Spring?Security?OAuth的token返回格式都是默認的,但是往往這個格式是不適配系統(tǒng)。本文將用一個接口優(yōu)雅的實現(xiàn)?Spring?Cloud?OAuth2?自定義token返回格式,需要的可以參考一下
    2022-06-06
  • Java 設計模式之適配器模式詳解

    Java 設計模式之適配器模式詳解

    設計模式(Design pattern)是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
    2021-11-11
  • Java經典快排思想以及快排的改進講解

    Java經典快排思想以及快排的改進講解

    今天小編就為大家分享一篇關于Java經典快排思想以及快排的改進講解,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Mybatis和orcale update語句中接收參數為對象的實例代碼

    Mybatis和orcale update語句中接收參數為對象的實例代碼

    Mybatis的 mapper.xml 中 update 語句使用 if 標簽判斷對像屬性是否為空值。本文重點給大家介紹Mybatis和orcale update語句中接收參數為對象的實例代碼,需要的朋友參考下吧
    2017-09-09

最新評論