0

The fundamental problem is to terminate a thread externally -safely.

An Event Dispatching Thread (EDT) spawns a new worker thread (workerThread). This workerThread has to complete a task. The task is completed in several iterations of a loop. Each iteration has two parts-read data(IO), compute data(Digest). workerThread can be signaled for cancellation by EDT at any time via a boolean flag(FLAG_CANCEL) inside workerThread's code. Here's the problem-the only time the flag is checked is after IO and/or after digest. This provides instant cancellation upto the sub-iteration level.

What I want is cancellation during IO or during Digest. Repetitively checking Thread.interrupted is the same as FLAG_CANCEL checking.That doesn't work. Since IO and Digest don't throw any InterruptedExceptions(nor can they be modified to do so), workerThread.interrupt() doesn't work(nothing in the loop gets interrupted).

  1. How to terminate IO or Digest in-situ?
  2. Can I use Thread.stop() safely(safely as in re-initializing unsafe-monitor-exposed-objects)?

Here's the EDT invocation

 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();

Here's the method for class 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());
    
   

}

Can I call workerThread.stop() and then use hasher safely afterwards in my next invocation of runnable?

Towards a solution-is it absolutely enough (towards ensuring nothing messes up in the next call to hasher from EDT)

  1. to do workerThread.stop in EDT &&

  2. reinitialize hasher, FLAG_CANCEL_HASHING &&

  3. ignore all fired events after cancellation,

  4. explicitly close fis(first having made it global)

    (basically make a new hasher instance in EDT)

Remember all is need is for termination during resource intensive IO or Digest to not affect the working of any successive calls to hasher. For e.g. after killing the thread by stop, will calling rutime.getRuntime.gc clean up the exposed objects and prevent any ill behaviour in the next call to hasher?

Community
  • 1
  • 1
lineage
  • 792
  • 1
  • 8
  • 20
  • Just for completeness: Java's InputStream.read() method does throw InterruptedIOException - so I am thinking that interrupt() on a thread on an I/O wait will abort the read with that exception... – moilejter Jul 23 '18 at 23:17
  • Possible duplicate of [Are Thread.stop and friends ever safe in Java?](https://stackoverflow.com/questions/1283328/are-thread-stop-and-friends-ever-safe-in-java) – VeeArr Jul 23 '18 at 23:52
  • java.io.InputStream.read() doesn't throw InterruptedIOException but IOException..doesn't help(JDK1.8) – lineage Jul 24 '18 at 19:24
  • [link]https://stackoverflow.com/questions/1283328/are-thread-stop-and-friends-ever-safe-in-java is rather specific to regex-matching(or something) but the jist is taht a thread is killable by stop if external objects are not being accessed-this is almost never the case. here,e.g, workerThread locks hasher and even if i reinitialized hasher after killing workerThread by stop, what about the things exposed inside md.digest of which I know nothing about? Object exposure isn't binding enough of a criteria to decide thread death, or is it? – lineage Jul 24 '18 at 19:41

0 Answers0