如何正常结束程序

在编程过程中,开发可能会困惑,不知道如何处理,interrupt 异常? 要理解interrupt 异常,先要搞明白,为什么会有interrupt 异常? 设计这套机制的背景是什么?

 

一个程序在运行,如何让他正常中断?

给程序发一个中断信号,在linux下,使用 kill pid

 

程序如何设计才能接收到,操作系统的中断信号?

 

实现一个shutdownhook。

参考 tomcat8 源码:


 

protected class CatalinaShutdownHook extends Thread {



        @Override

        public void run() {

            try {

                if (getServer() != null) {

                    Catalina.this.stop();

                }

            } catch (Throwable ex) {

                ExceptionUtils.handleThrowable(ex);

                log.error(sm.getString("catalina.shutdownHookFail"), ex);

            } finally {

                // If JULI is used, shut JULI down *after* the server shuts down

                // so log messages aren't lost

                LogManager logManager = LogManager.getLogManager();

                if (logManager instanceof ClassLoaderLogManager) {

                    ((ClassLoaderLogManager) logManager).shutdown();

                }

            }

        }

    }



Catalina.java

public void start() {

…

            Runtime.getRuntime().addShutdownHook(shutdownHook);//shutdownHook注册

}

try {

            Server s = getServer();

            LifecycleState state = s.getState();

            if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0

                    && LifecycleState.DESTROYED.compareTo(state) >= 0) {

                // Nothing to do. stop() was already called

            } else {

                s.stop();// 让组件停下来,并销毁

                s.destroy();

            }

        } catch (LifecycleException e) {

            log.error("Catalina.stop", e);

        }

控制程序正常结束(退出建议)

调用每个组件的stop方法,清理程序,包括

1 设置停止运行标记位。 (退出循环)

2 停止程序运行,比如 网络调用socket.stop等等

3 给线程发送中断请求。比如,

工具类的中断

AbstractThreadPool,提供2个中断方法 shutdown,shutdownNow

shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。而shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。

线程的中断

t.interrupt();

 try {

                t.join(1000); //最多等待1s 结束线程

  } catch (InterruptedException e) {

                // Ignored

            }

 

4 代码清理工作。

以上操作需要保证数据的一致性,不能简单的退出。

 

看看 Catalina.this.stop(); 的源码

 

...

 

 

protected void stopInternal() throws LifecycleException {

        setState(LifecycleState.STOPPING);

        fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);

        // Stop our defined Services

        for (int i = 0; i < services.length; i++) {

            services[i].stop();//

        }

        globalNamingResources.stop();
        stopAwait();// 调用 Thread awaitThread的 interrupt方法。

    }

 

stopAwait 实现

t.interrupt();

            try {

                t.join(1000);

            } catch (InterruptedException e) {

                // Ignored

            }

 

 

最后再谈谈,当捕捉到 interrupt 异常程序如何处理?

要明白,这个异常意味着,程序要求正常停止,如果程序不是线程执行的最外层(栈调用的第一层),处理完后(参考上述的退出建议),需要把中断请求继续往上一层传递。

 

参考代码

1

2

3

4

5

6

7

8

public static void sleep(long millis)

  throws InterruptedException {

  while (/* ... */) {

    if (Thread.interrupted()) {

      throw new InterruptedException();

    }

  }

}

请记住,Thread.interrupted() 不仅仅是返回标识变量的值,而且会将标识变量的值设置为 false。因此,一旦抛出 InterruptedException 异常,标志变量将会重置。线程不再收到任何拥有者发送的中断请求。

或者

1

2

3

4

5

6

try {

  Thread.sleep(100);

} catch (InterruptedException ex) {

  Thread.currentThread().interrupt(); // Here!

  throw new RuntimeException(ex);

}

你可能感兴趣的:(Java)