2

I currently have a tread that starts when you press a button on a GUI, this thread basicly starts to download files, but I wanted to implement that you can stop the tread, which worked fine with t.suspend(); but it is deprecated, so I tried to use t.wait(); and t.notify();, and the problem with this is that the wait one throws an exception "Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException" every time I try to pause it.

Start Download Button:

t = new TestTread();
 t.start();

Pause:

        try {
        t.wait();
    } catch (InterruptedException ex) {
        Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }

Continue:

t.notify();

The Thread Class

public class DownloaderThread extends Thread{

 @Override
 public void run(){
    Download();
 }

public void Download() {
    URL url = new URL(ftpUrl); 
    URLConnection conn = url.openConnection(); 
    InputStream inputStream = conn.getInputStream(); 
    FileOutputStream outputStream = new FileOutputStream(savePath); 
    byte[] buffer = new byte[BUFFER_SIZE]; 
    int bytesRead = -1; 
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, bytesRead);
    } 
   outputStream.close(); 
   inputStream.close();
}

The download works fine, its download the file without any errors, its just I cannot stop the thread with t.wait. Am I doing something wrong or am I implementing the wait in a wrong way?

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
peti446
  • 330
  • 1
  • 4
  • 12
  • Interrupt the thread. – Neijwiert Nov 26 '15 at 14:01
  • 2
    You should read what the `wait()/notify()` mechanism actually is. It's not a "pause" mechanism (although it can be used to achieve that). – Kayaman Nov 26 '15 at 14:01
  • 3
    You misunderstood the `wait()`. This will not suspend the Thread/Object you call it on, it will let the Thread sleep which is calling it. It sleeps until someone calls `notifly()` on that exact Object! – ParkerHalo Nov 26 '15 at 14:01
  • 1
    I don't thin interruption would be sufficient in what the OP describes. I would advise to construct a type of pre/post set of conditions where the thread would execute only given a condition is met. – e.doroskevic Nov 26 '15 at 14:02

2 Answers2

3

You need to change your download() method to check for a stop or pause event and then stop or pause the thread. It has to be this way as the JVM does not know what steps need to be done in order to safely pause/stop the thread.

You may end up using wait but not the way you are using it. wait causes the currently running thread to wait until some calls notify on the object you have called wait on.

In the download method you have a loop (read a block, write a block). You should add two checks in the loop.

while ((bytesRead = inputStream.read(buffer)) != -1) {
      outputStream.write(buffer, 0, bytesRead);
      if(paused) {
         // How do you want to handle pausing? See below for options.
      }
      if(stopped) {
         // delete the file and close the streams. 
      }
} 

How you handle pausing is up to you. I can see two options: Save what you have as ".incomplete" and later restart the download using the Range header or continue looping with a pause (Thread.sleep, Object.wait or whatever). I would go with the first option (Range Header). It is more work but also more robust.

Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81
  • So i have this method in the download(); `byte[] buffer = new byte[1024]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); }` i would need to stop the while, but i have no idea about how to do so, as when i add aother statement to check if its paused or not it just stop downloading at all and i canot resume it. – peti446 Nov 26 '15 at 15:35
  • Updated. The comment should be added to the question. I have done so. – Michael Lloyd Lee mlk Nov 26 '15 at 15:42
  • What if instance handling the pause i used as @edharned suggested and sleep the download thread for a second until it is not paused? Something like: `while(threadSuspended){ try { Thread.sleep(1000); } catch (InterruptedException ex) { } }` It is a good practice doing it in this way ? – peti446 Nov 26 '15 at 15:55
  • You have a connection open to the remote server and are not using it. I'd not do it that way as it is likely that the remote server will disconnect you. A few examples on how to resume a download exist here on [stack overflow](http://stackoverflow.com/questions/6237079/resume-http-file-download-in-java). – Michael Lloyd Lee mlk Nov 26 '15 at 15:58
0

Forget the wait/notify. You are not using them correctly.

Set up a :

volatile boolean pause = false;

Now inside your download method:

while(pause) try {Thread.sleep(1000); } catch (InterruptedException ignore) {}

Setting pause true/false controls how long the thread sleeps.

edharned
  • 1,884
  • 1
  • 19
  • 20