如何在客户端服务器多线程中停止服务器

我正在用 java 实现一个多线程客户端-服务器应用程序。我想在这个程序中实现JDBC,我希望我的服务器在启动时从数据库中检索数据。我会将这些数据存储在我的collection实例中,对数据执行操作,当服务器完成执行时,我需要将数据存储回数据库。问题是服务器处于无限循环等待客户端,我无法弄清楚如何让服务器停止。


这是我的服务器程序:


import java.io.*;

import java.text.*;

import java.util.*;

import java.net.*;


public class Server 

{

    public static void main(String[] args) throws IOException 

    {

        // server is listening on port 5056

        ServerSocket ss = new ServerSocket(5056);


        // running infinite loop for getting

        // client request

        while (true) 

        {

            Socket s = null;


            try {

                // socket object to receive incoming client requests

                s = ss.accept();


                System.out.println("A new client is connected : " + s);


                // obtaining input and out streams

                DataInputStream dis = new DataInputStream(s.getInputStream());

                DataOutputStream dos = new DataOutputStream(s.getOutputStream());


                System.out.println("Assigning new thread for this client");


                // create a new thread object

                Thread t = new ClientHandler(s, dis, dos);


                // Invoking the start() method

                t.start();

            }

            catch (Exception e) {

                s.close();

                e.printStackTrace();

            }

        }

    }

}


// ClientHandler class

class ClientHandler extends Thread 

{

    DateFormat fordate = new SimpleDateFormat("yyyy/MM/dd");

    DateFormat fortime = new SimpleDateFormat("hh:mm:ss");

    final DataInputStream dis;

    final DataOutputStream dos;

    final Socket s;



    // Constructor

    public ClientHandler(Socket s, DataInputStream dis, DataOutputStream dos) 

    {

        this.s = s;

        this.dis = dis;

        this.dos = dos;

    }

犯罪嫌疑人X
浏览 202回答 2
2回答

收到一只叮咚

概述好问题!重申上述评论中所述的内容,您正在寻找服务器端关闭。有一些方法可以处理这种情况,我可以用一个简短的例子来解释它。执行服务器我将根据这个例子运行一个修改过的例子。下面找到服务器实现。class NetworkService implements Runnable {    private final ServerSocket serverSocket;    private final ExecutorService pool;    private final AtomicBoolean shouldExit;    public NetworkService(int port, int poolSize) throws IOException {        serverSocket = new ServerSocket(port);        pool = Executors.newFixedThreadPool(poolSize);        shouldExit = new AtomicBoolean(false); // Thread-safe boolean    }    public void run() { // run the service        try {           // While we should not exit           while(!shouldExit.get()) {             try {                 pool.execute(new ClientHandler(serverSocket.accept()));             } catch (SocketException e) {                 if(shouldExit.get()) break; // Poison pill has been delivered, lets stop                 // Error handling             }           }        } catch (IOException ex) {           pool.shutdown();        }       // Clean up the thread pool       shutdownAndAwaitTermination();    }}class ClientHandler implements Runnable {    private final Socket socket;    ClientHandler (Socket socket) { this.socket = socket; }    public void run() {        ...    }    ... }在这里,您将修改当前的服务器代码以恐吓此结构。您目前有类似的妆容,但我们在这里添加了ExecutorService.一个 Executor 提供管理终止的方法和可以生成 Future 以跟踪一个或多个异步任务的进度的方法。通过将您的 ClientHandler 分派到ExecutorService,您正在使用ThreadPool. 虽然这带来了很多好处,但最重要的是您可以更好地控制多线程服务,ThreadPool管理线程利用率,并且应用程序效率将大大提高。以下是您尝试关闭和终止所有剩余线程的方法:void shutdownAndAwaitTermination(ExecutorService pool) {    pool.shutdown(); // Disable new tasks from being submitted    try {        // Wait a while for existing tasks to terminate        if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {            pool.shutdownNow(); // Cancel currently executing tasks            // Wait a while for tasks to respond to being cancelled        if (!pool.awaitTermination(60, TimeUnit.SECONDS))            System.err.println("Pool did not terminate");        }    } catch (InterruptedException ie) {        // (Re-)Cancel if current thread also interrupted        pool.shutdownNow();        // Preserve interrupt status        Thread.currentThread().interrupt();    }}现在,问题仍然是我们如何关闭服务器?上面的代码显示了一个改进的结构,但仍然存在阻塞的问题serverSocket.accept()!解决方案想到这个场景时,有两个想法浮现在脑海中;CLI 或 GUI。两者具有相同的语义,最终由您决定。出于解释的目的,我将参考 CLI 方法。毒丸如果您实现new Thread()处理来自 CLI 的所有传入命令,则该线程将充当毒丸。这个想法是向目标递送毒丸,使其可以醒来/执行并死亡。该线程会将shouldExit原子布尔值更改为true并创建一个new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()).close();以连接到ServerSocket并立即关闭它。在上面的代码中,应用程序将不再阻塞serverSocket.accept(). 相反,它将进入 try catchSocketExceptions并测试是否使用了毒丸;如果是,那么让我们清理,如果不是,让错误处理。暂停您还可以在 上设置超时,ServerSocket以便每次在该时间间隔内无法与myServer.setSoTimeout(2000);. 这将抛出一个InterruptedIOException并且 可以类似于毒丸处理,通过 CLI 命令更改标志并检查它是否应该在 catch 块中退出。如果它应该退出,让我们清理,否则让错误处理。

九州编程

您可以将模式标志与 volatile 布尔变量一起使用,并且您应该将它放在 'while' 中 - 当处理完成时,将其设置为 false 并且服务器将停止。另一种方法 - 使用线程池并等待它们在服务器的主线程中完成。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java