首页 > 编程语言 >Java的ExecutorService的shutdownNow()方法并不能保证一定会结束线程的解决办法

Java的ExecutorService的shutdownNow()方法并不能保证一定会结束线程的解决办法

时间:2022-11-29 15:24:42浏览次数:74  
标签:Java shutdownNow java util 线程 import executingThreads

这几天使用ExecutorService的时候遇到了在Task内部进行读取文件操作而导致死循环的问题,当我试图调用shutdownNow()方法的时候,发现并不是像我预想的一样会理解结束线程。我在JDK的API文档中看到了相关解释,Oracle官方的解释是并不保证会结束线程。原文在此:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html

我这里引述一下,注意红色部分:

  • shutdownNow

    List<Runnable> shutdownNow()
    Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.

    This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.

    There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

    Returns:
    list of tasks that never commenced execution
    Throws:
    SecurityException - if a security manager exists and shutting down this ExecutorService may manipulate threads that the caller is not permitted to modify because it does not hold RuntimePermission("modifyThread"), or the security manager's checkAccess method denies access.

我搜索了之后,发现国外有个老哥实现了一个ExecutorService貌似可以结束线程,但是我没有仔细看,我稍微修改了一下,让它能够在我的项目中跑起来,目前看没有什么问题,

国外老哥的代码在这里:java - How to force terminate all workers in ThreadPoolExecutor immediately - Stack Overflow

我略微修改了一下,代码如下:

package com.xxx.api.utils;

import cn.hutool.core.thread.ThreadFactoryBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class KillableThreadPoolExecutor extends ThreadPoolExecutor {

    private final Map<Runnable, Thread> executingThreads;

    public KillableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, String threadNamePrefix) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new LinkedBlockingDeque<Runnable>(), ThreadFactoryBuilder.create().build());
        executingThreads = new HashMap<>(maximumPoolSize);
    }

    @Override
    protected synchronized void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        executingThreads.put(r, t);
    }

    @Override
    protected synchronized void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if(executingThreads.containsKey(r)) {
            executingThreads.remove(r);
        }
    }

    @Override
    public synchronized List<Runnable> shutdownNow() {
        List<Runnable> runnables = super.shutdownNow();
        for(Thread t : executingThreads.values()) {
            t.stop();
        }
        return runnables;
    }
}

 

使用:

       KillableThreadPoolExecutor killableThreadPoolExecutor = new KillableThreadPoolExecutor(1, 1, 5, TimeUnit.SECONDS, "");
  
               FutureTask<?> futureTask = new FutureTask(() -> {               
               ResultEntity docTmp = null;
               //耗时操作可能会死循环,所以放到线程中进行监控
               docTmp = new ResultEntity(inPathStream);
               return docTmp;
            });
            
            Future<?> submit = killableThreadPoolExecutor.submit(futureTask);

            try {
                //System.out.println(DateUtil.now());
                //等待20s,否则认为超时,死循环了
                Object obj = futureTask.get(20, TimeUnit.SECONDS);
               // System.out.println(DateUtil.now());
                if (null == obj) {
                    //超时
                    pdfPageCount = 0;
                } else {
                    doc = (ResultEntity) obj;
                    //页数
                    pdfPageCount = doc.getPageCount();
                }
            } catch (TimeoutException e) {
                killableThreadPoolExecutor.shutdownNow();
            }
         catch (Exception e) {            
            killableThreadPoolExecutor.shutdownNow();
        }
        finally {
                //System.out.println(DateUtil.now());
                killableThreadPoolExecutor.shutdownNow();
            }

 

标签:Java,shutdownNow,java,util,线程,import,executingThreads
From: https://www.cnblogs.com/sixiweb/p/16935453.html

相关文章

  • day07_java_数组
    d07Java数组(p51-p59)1.什么是数组?数组就是一组数的集合。数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后顺序排列组合而成。......
  • Java8新特性
    1.利用distinct去重 并保持数组的顺序ArrayList<Integer>list=newArrayList();list.add(7);list.add(5);list.add(9);list.a......
  • java如何高效地读取一个超大文件?(四种方式分析对比)
    读取大文件的四种方式本地压缩了一个文件夹,大概500M左右。虽然不是很大但是,相对还可以。方法1:Guava读取Stringpath="G:\\java书籍及工具.zip";Files.readLines(new......
  • java基础多线程之共享数据
    java基础巩固笔记5-多线程之共享数据线程范围内共享数据ThreadLocal类多线程访问共享数据几种方式本文主要总结线程共享数据的相关知识,主要......
  • Java 注解和反射(六)获取泛型,注解信息
    反射操作泛型**Java采用泛型擦出的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免除强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类......
  • JAVA面试题--Dubbo
    Dubbo1.Dubbo是什么?2.为什么要用Dubbo?3.Dubbo和Dubbox有什么区别?4.dubbo都支持什么协议,推荐用哪种?5.Dubbo需要Web容器吗?6.Dubbo内置了哪几种服务容器?7.Dubbo......
  • python,进程线程
    一、什么是进程/线程https://blog.csdn.net/qq_69447411/article/details/1263134261、引论众所周知,CPU是计算机的核心,它承担了所有的计算任务。而操作系统是计算机......
  • JAVA面试题--Java高并发
    Java高并发1.什么是进程2.什么是线程3.进程间如何通讯4.线程间如何通讯5.同步和异步有何不同,在什么情况下分别使用它们?举例说明6.进程调度算法7.Java中Unsafe类详......
  • Java加载js
    Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持js的属性设置为trueAndroid(Java)与JavaScript(HTML)交互有四种情况:1)Android(Java)调......
  • 用 Java 对 hbase 进行CRUD增删改查操作
    本文以HBase0.90.2为例,介绍如何在Windows系统,EclipseIDE集成环境下,使用Java语言,进行HBase客户端编程,包含建立表、删除表、插入记录、删除记录、各种方式下的查询操作等。......