退出JVM前,如何优雅的结束当前任务?

假定场景
线程1在进行耗时任务,例如从网络读取数据。我们的期望时间是30s内结束,如果超过30s则直接停止该线程,并开始执行JVM退出流程。

如何实现该种场景?
思路1
直接对线程1执行interupt()方法。可以这样做,但是要注意使用场景,摘自interupt()方法的javadoc:

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int)methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.
If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.
If none of the previous conditions hold then this thread's interrupt status will be set.

思路2
调用线程的stop方法
不推荐!!stop方法已被标记为deprecated,随时可能被移除,且有很多已知问题。

思路3
实现方式:以如下代码为例,main ---fork1---> executeThread ---fork2---> runner(daemon)。当fork2成功后,通过runner.join(),使得executeThread开始等待runner的结束。此时如果main线程执行executeThread.interupt(),则executeThread抛出InterruptedException并退出,由于runner是daemon线程,在main执行完后没有非daemon属性的用户线程在执行了,JVM开始执行退出流程。
思路3样例代码:
main

public static void main(String[] args) {

        ThreadService service = new ThreadService();
        long start = System.currentTimeMillis();
        service.execute(() -> {
            //load a very heavy resource.
            /*while (true) {

            }*/
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        service.shutdown(10000);
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

ThreadService.java

public class ThreadService {

    private Thread executeThread;

    private boolean finished = false;

    public void execute(Runnable task) {
        executeThread = new Thread() {
            @Override
            public void run() {
                Thread runner = new Thread(task);
                runner.setDaemon(true);

                runner.start();
                try {
                    runner.join();
                    finished = true;
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }
            }
        };

        executeThread.start();
    }

    public void shutdown(long mills) {
        long currentTime = System.currentTimeMillis();
        while (!finished) {
            if ((System.currentTimeMillis() - currentTime) >= mills) {
                System.out.println("任务超时,需要结束他!");
                executeThread.interrupt();
                break;
            }

            try {
                executeThread.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("执行线程被打断!");
                break;
            }
        }

        finished = false;
    }
}

你可能感兴趣的:(退出JVM前,如何优雅的结束当前任务?)