如何优雅的关闭java进程。(避免 kill -9 )

Reading time ~1 minute

一、为什么不能用kill -9 :

项目中需要一个死循环不断从队列中获取消息存入数据库,但是,当项目需要重启时, 操作人员往往会用kill -9 直接关闭java进程。导致数据丢失。为了解决这个问题, 用到下面技术,

1. 一个是 java的hook ,钩子函数,在虚拟机启动时注册一个钩子函数,
   当执行kill时,java虚拟机会对钩子函数中资源进行回收。

2. 多线程,用线程启动死循环,然后钩子函数接收到关闭命令时传递死循环标志位。
   示例代码如下:

二、线程方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class MyRunnable implements Runnable {
	private volatile boolean quit =false;

	public boolean isQuit() {
		return quit;
	}

	public void setQuit(boolean quit) {
		this.quit = quit;
	}

	public void run() {
		int i = 0;
		while (!quit) {
			doStuff(i++);
		}
	}

	private void doStuff(int n) {

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("----->" + n);
	}

}


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestThread {

	public static void main(String[] args) {

		final MyRunnable test = new MyRunnable();
		

		final ExecutorService executorService = Executors.newCachedThreadPool();
		executorService.execute(test);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				test.setQuit(true);
				sleep(5);
					while (test.isQuit()&&!executorService.isShutdown()) {
						System.out.println("thread is closed, now ,close executorService!"); // optional

						executorService.shutdown();
					}

			}

			private void sleep(int n) {
				try {
					Thread.sleep(1000*n);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});

	}

}

taste是个玄学

Published on November 16, 2022

印度工人

Published on August 30, 2022