【问题标题】:Pause/Resume a Thread暂停/恢复线程
【发布时间】:2015-11-26 13:59:36
【问题描述】:

我目前有一个在你按下 GUI 上的按钮时启动的踏板,这个线程基本上开始下载文件,但我想实现你可以停止踏板,这在 t.suspend(); 上工作得很好,但它已被弃用,所以我尝试使用t.wait();t.notify();,问题是每次我尝试暂停时,等待的人都会抛出异常“线程“AWT-EventQueue-0”java.lang.IllegalMonitorStateException中的异常”它。

开始下载按钮:

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

暂停:

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

继续:

t.notify();

线程类

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

下载工作正常,下载文件没有任何错误,只是我无法使用 t.wait 停止线程。 我做错了什么还是我以错误的方式实现了等待?

【问题讨论】:

  • 中断线程。
  • 您应该阅读wait()/notify() 机制实际上是什么。它不是一种“暂停”机制(尽管它可以用来实现)。
  • 您误解了wait()。这不会暂停你调用它的线程/对象,它会让调用它的线程休眠。它会一直休眠,直到有人在那个确切的对象上调用 notifly()
  • 我不认为 OP 描述的中断就足够了。我建议构建一种类型的前/后条件集,其中线程仅在满足条件的情况下才会执行。

标签: java multithreading


【解决方案1】:

您需要更改 download() 方法以检查停止或暂停事件,然后停止或暂停线程。必须采用这种方式,因为 JVM 不知道需要执行哪些步骤才能安全地暂停/停止线程。

您最终可能会使用wait,但不是您使用它的方式。 wait 导致当前正在运行的线程等待,直到对您已调用 wait 的对象调用 notify

在下载方法中有一个循环(读取一个块,写入一个块)。您应该在循环中添加两个检查。

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. 
      }
} 

如何处理暂停取决于您。我可以看到两个选项:将您拥有的内容保存为“.incomplete”,然后使用Range 标头重新开始下载,或者暂停循环(Thread.sleep、Object.wait 或其他)。 我会选择第一个选项(范围标题)。这是更多的工作,但也更强大。

【讨论】:

  • 所以我在download()中有这个方法; byte[] buffer = new byte[1024]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } 我需要停止一段时间,但我不知道该怎么做,因为当我添加另一个语句来检查它是否暂停时它只是停止下载并且我无法恢复它。
  • 已更新。评论应该添加到问题中。我已经这样做了。
  • 如果实例处理我使用@edharned 建议的暂停并将下载线程休眠一秒钟直到它没有暂停怎么办?类似:while(threadSuspended){ try { Thread.sleep(1000); } catch (InterruptedException ex) { } } 以这种方式这样做是一个好习惯?
  • 您有一个到远程服务器的连接打开并且没有使用它。我不会那样做,因为远程服务器很可能会断开你的连接。 stack overflow 上有一些关于如何恢复下载的示例。
【解决方案2】:

忘记等待/通知。您没有正确使用它们。

设置一个:

volatile boolean pause = false;

现在在您的下载方法中:

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

设置 pause true/false 控制线程休眠的时间。

【讨论】:

    猜你喜欢
    • 2015-02-21
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 2010-12-28
    • 2020-08-13
    • 2011-08-02
    相关资源
    最近更新 更多