代码之家  ›  专栏  ›  技术社区  ›  htshame

停止已经运行的线程

  •  1
  • htshame  · 技术社区  · 7 年前

    我有两个api:一个启动线程,另一个停止线程。我可以通过调用 /start API,但我无法通过调用 /stop 应用程序编程接口。好像 Executor#stop() 什么都不做。

    我的 RestController

    @Autowired
    private Executor executor;
    
    @RequestMapping(path = "/start", method = GET)
    public ResponseEntity<HttpStatus> startLongTask() {
        executor.start();
        return ResponseEntity.ok(HttpStatus.OK);
    }
    
    @RequestMapping(path = "/stop", method = GET)
    public ResponseEntity<HttpStatus> stopLongTask() {
        executor.stop();
        return ResponseEntity.ok(HttpStatus.OK);
    }
    

    我的 Executor :

    @Component
    public class Executor {
    
        @Value("${threads.number}")
        private int threadsNumber;
    
        private ExecutorService executorService;
    
        @Autowired
        private OtherService otherService;
    
        @PostConstruct
        private void init() {
            executorService = Executors.newFixedThreadPool(threadsNumber);
            executorService = Executors.newScheduledThreadPool(threadsNumber);
        }
    
        /**
         * Start.
         */
        public void start() {
            executorService.submit(() -> otherService.methodImExecuting());
        }
    
        /**
         * Stop.
         */
        @PreDestroy
        publicvoid stop() {
            executorService.shutdownNow();
            try {
                if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow();
            }
        }
    }
    

    这是你的答案 methodImExecuting

    @Component
    public class OtherService {
    
        public void methodImExecuting() {
            List<SomeObject> dataList = repository.getDataThatNeedsToBeFilled();
            for (SomeObject someObject : dataList) {
                gatewayService.sendDataToOtherResourceViaHttp(someObject);
            }
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   Torsten Fehre    7 年前

    简而言之:你不能停止一个不合作的正在运行的线程。有一个不推荐的 destroy() 方法,但这将导致VM处于“坏”状态。

    结束线程的唯一可能就是中断它。但是检查中断是线程本身的任务。

    methodImExcecuting 应该是这样的:

    void methodImExecuting() throws InterruptedException {
        // it depends on your implementation, I assume here that you iterate 
        // over a collection for example
        int loopCount = 0;
        for (Foo foo : foos) {
            ++loopCount;
            if (loopCount % 100 == 0) {
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
            ...
        }
    

    这取决于你的实现,如果你的线程被中断,你需要多久检查一次。但事实上 executorService.shutdownNow(); 只会设置 interrupted 设置标志,然后抛出 InterruptedException

        2
  •  1
  •   tomas    7 年前

    运行的线程必须对中断信号做出反应

    Thread.currentThread().isInterrupted()
    

    否则,中断信号的发送不起作用。

    Difference between shutdown and shutdownNow of Executor Service