简体   繁体   English

终止应用程序和ScheduledExecutorService; 线

[英]Terminating application and ScheduledExecutorService; Thread

I have the following logic (simplified): 我有以下逻辑(简化):

public class Application {

    public static volatile boolean stopServer;
    private static ScheduledExecutorService taskScheduler;

    private static Thread listenerThread;

    public static synchronized void switchStopServer() {
        stopServer = true;

        listenerThread.interrupt();
        taskScheduler.shutdownNow();
    }

    public static void main(String[] args) {
            int threadPoolSize = 4;
            taskScheduler = Executors.newScheduledThreadPool(threadPoolSize);

            listenerThread = new ListenerThread();
            taskScheduler.schedule(listenerThread, 0, TimeUnit.NANOSECONDS);
    }

}

public class ListenerThread extends Thread {

    private static ServerSocket serverSocket;
    private Socket socketConnection;

    @Override
    public void run() {
         while (!Application.stopServer) {
              try {
                   socketConnection = serverSocket.accept();
                   new CommunicatorThread(socketConnection).start();
              } catch (SocketException e) {
              } catch (Exception e) {
              }
         }  
    }

    private static void closeServerSocket() {
         try {
              if (serverSocket != null && !serverSocket.isClosed()) serverSocket.close();
         } catch (Exception e) { }
    }

    @Override
    public void interrupt() {
         closeServerSocket();
         super.interrupt();
    }

}

What I want to achieve, is to terminate Thread s the proper way. 我想要实现的是以正确的方式终止Thread First of all, is this ( switchStopServer() ) the correct way to do that, or are there any better solutions? 首先,这是( switchStopServer() )正确的方法,还是有更好的解决方案?

I'm a little confused with the ScheduledExecutorService , because shutdownNow() does not interrupt the Thread s, neither does ScheduledFuture.cancel(true) (at least for me it doesn't), so I can't interrupt ServerSocket.accept() . 我对ScheduledExecutorService有点困惑,因为shutdownNow()不会中断Thread s, ScheduledFuture.cancel(true)也没有(至少对我来说它没有),所以我不能打断ServerSocket.accept() I know, in my example there is no need for the ScheduledExecutorService , but in my real application there is. 我知道,在我的例子中,不需要ScheduledExecutorService ,但在我的实际应用程序中有。

Your problem I believe is that you are confusing Thread and Runnable . 我相信你的问题是你在混淆ThreadRunnable Even though ListenerThread extends Thread , it is actually not it's own thread. 即使ListenerThread扩展了Thread ,它实际上也不是它自己的线程。 The thread is managed by the ExecutorService thread-pool which is just calling your run() method. 该线程由ExecutorService线程池管理,该线程池只调用run()方法。 This is only [sort of] working because Thread also implements Runnable . 这只是[有点]工作,因为Thread也实现了Runnable When you call ListenerThread.interrupt() you are not interrupting the thread in the thread-pool although you are calling your interrupt() method but just directly in the calling thread. 当你调用ListenerThread.interrupt()你不是在打断线程池中的线程,尽管你正在调用你的interrupt()方法而只是直接在调用线程中。 This should close the socket since it calls closeServerSocket() from the outside. 这应该关闭套接字,因为它从外部调用closeServerSocket()

When you call ScheduledFuture.cancel(true) or shutdownNow() , the pool thread(s) should be interrupted but this will not call your interrupt() method there. 当您调用ScheduledFuture.cancel(true)shutdownNow() ,应该中断线程,但这不会调用您的interrupt()方法。 You can test for the interruption by using Thread.currentThread().isInterrupted() in your run() method. 您可以在run()方法中使用Thread.currentThread().isInterrupted()来测试中断。

You should change ListenerThread from extending Thread and instead have it just implement Runnable ( see edit below ). 您应该从扩展Thread更改ListenerThread ,而是让它只实现Runnable请参阅下面的编辑 )。 You will want to do something like the following loop in your run() method: 您将需要在run()方法中执行类似以下循环的操作:

while (!Application.stopServer && !Thread.currentThread().isInterrupted()) {

To interrupt the accept() method, you are going to have to close the serverSocket from another thread. 要中断accept()方法,您将不得不从另一个线程关闭serverSocket Most likely this will be done by the thread that is calling interrupt() . 这很可能是由调用interrupt()的线程完成的。 It should close the socket, shutdownNow() or cancel() the thread-pool, and then it can wait for the pool to terminate. 它应该关闭套接字, shutdownNow()cancel()线程池,然后它可以等待池终止。

Edit: 编辑:

Actually, I wonder why you are using a pool for your ListenerThread since there will only ever be one of them, it is being scheduled immediately, and it is just starting a new thread on any connection directly. 实际上,我想知道你为什么要为ListenerThread使用一个池,因为它只会有一个,它会被立即调度,它只是直接在任何连接上启动一个新线程。 I would remove your taskScheduler pool entirely, keep ListenerThread extending Thread , and just call new ListenerThread().start(); 我会完全删除你的taskScheduler池,让ListenerThread继续扩展Thread ,然后只调用new ListenerThread().start(); .

The outer thread would still just close the serverSocket to stop the ListenerThread . 外部线程仍然只是关闭serverSocket以停止ListenerThread If you also need to close all of the connections as well then the ListenerThread needs to keep a collection of the socketConnection around so it can call close() on them when the accept() throws an IOException . 如果你还需要关闭所有连接,那么ListenerThread需要保留socketConnection的集合,这样当accept()抛出IOException时它可以调用它们的close()

Also, currently you have private Socket socketConnection; 另外,目前你有private Socket socketConnection; which is misleading because it will change after every call to accept() . 这是误导性的,因为它会在每次调用accept()后发生变化。 I'd rewrite it as: 我把它重写为:

 Socket socketConnection = serverSocket.accept();
 new CommunicatorThread(socketConnection).start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM