首页 > 解决方案 > 检查所有进度标志后,如何终止进入资源密集型方法的java线程?

问题描述

基本问题是在外部安全地终止线程。

事件调度线程 (EDT) 会产生一个新的工作线程 (workerThread)。这个workerThread必须完成一个任务。该任务在一个循环的多次迭代中完成。每次迭代都有两部分——读取数据(IO),计算数据(Digest)。EDT 可以随时通过 workerThread 代码中的布尔标志 (FLAG_CANCEL) 向 workerThread 发出取消信号。这是问题所在 - 检查标志的唯一时间是在 IO 和/或摘要之后。这提供了高达子迭代级别的即时取消。

我想要的是IO 或Digest期间取消。重复检查 Thread.interrupted 和检查 FLAG_CANCEL 是一样的。那是行不通的。由于 IO 和 Digest 不会抛出任何 InterruptedExceptions(也不能对其进行修改),因此 workerThread.interrupt() 不起作用(循环中的任何内容都不会被中断)。

  1. 如何就地终止 IO 或 Digest?
  2. 我可以安全地使用 Thread.stop() 吗(像重新初始化 unsafe-monitor-exposed-objects 一样安全)?

这是 EDT 调用

 private final Runnable runnable= new Runnable() {
    @Override
    public void run() {
        try {

            //hasher is a global instance in EDT of Hasher class

            hasher.hash(file);

        } catch (NoSuchAlgorithmException ex) {
            //do something
            

        } catch (IOException ex) {
            //do something
        } 
        catch (InterruptedException ex) {
             //do something
        }

    }

};
Thread workerThread=new Thread(runnable);
workerThread.setDaemon(true);
workerThread.start();

这是Hasher类的方法

synchronized public String hash(File file) throws NoSuchAlgorithmException, FileNotFoundException, IOException 
{

    FLAG_CANCEL_HASHING = false;//global
    byte[] buffer =new buffer[calculateBufferSize()];
    MessageDigest md = MessageDigest.getInstance(algorithm);
    FileInputStream fis = new FileInputStream(file);
    int bytesRead;
    float totalBytesRead = 0;
    
    //start hashing
    while ((bytesRead = fis.read(buffer)) != -1)//IO
    {

        //check before Digest    

        if (FLAG_CANCEL_HASHING) 
        {              
            fireCancellationEvent();
            return null;               
          
        }
       

        md.update(buffer, 0, bytesRead);//Digest
        
      
           //check before IO

        iif (FLAG_CANCEL_HASHING) 
        {              
            fireCancellationEvent();
            return null;               
          
        }
        
        
        totalBytesRead += bytesRead;         
        fireProgressEvent(totalBytesRead );
        

    }
    

    
    fis.close();

    return  toHexString(md.digest());
    
   

}

我可以调用 workerThread.stop() 然后在下一次调用 runnable 时安全地使用 hasher 吗?

寻求解决方案- 是否足够(确保在下一次从 EDT 调用 hasher 时不会出现任何问题)

  1. 在 EDT && 中做 workerThread.stop

  2. 重新初始化哈希,FLAG_CANCEL_HASHING &&

  3. 取消后忽略所有触发的事件,

  4. 明确关闭 fis(首先使其成为全球性的)

    (基本上在 EDT 中创建一个新的哈希实例)

请记住,所有需要的是在资源密集型 IO 或摘要期间终止,以免影响对哈希器的任何连续调用的工作。例如,在通过停止终止线程之后,调用 rutime.getRuntime.gc 是否会清理暴露的对象并防止在下一次调用 hasher 时出现任何不良行为?

标签: javamultithreading

解决方案


推荐阅读