2011-03-21 61 views
2

嘿家伙 我在我的android应用程序的oncreate之外使用了runnable,我已经使用线程来设置ProgressBar的进度。我不知道的是,当停止按钮被按下时,如何停止/取消线程,因为thread.stop不是一个方法,以及如何从该方法恢复,甚至如何破坏线程。如何销毁一个线程,暂停/挂起一个线程,恢复/运行一个线程?

我知道我必须在runnable中创建一些方法和成员,但我不完全知道是什么?

+0

你有没有想过使用的AsyncTask呢?它具有更新进度指示器的内置方法,如果需要也可以轻松取消。 – Squonk 2011-03-21 22:06:16

回答

3

Thread.stop()不再使用,因为它被认为是危险的:http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

您必须让线程由于变量变化而自然结束。该链接还提供了一些关于如何实现这一目标的建议。

public class MyThread extends Thread { 

    private boolean threadDone = false; 

    public void done() { 
     threadDone = true; 
    } 

    public void run() { 
     while (!threadDone) { 
      // work here 
      // modify common data 
     } 
    } 

}

警告:请确保您无论是在循环代码中使用guarded block,一个方法阻止自己,或Thread.sleep(..)。如果你不了解保护区块,Thread.sleep是最原始的,但它会起作用。您也可以永远等待,并使用中断机制取消当您使用等待或睡眠时在try-catch块中以InterruptedException形式抛出的线程。为此,请使用!Thread.currentThread().isInterrupted()作为环路保护条件,然后使用Thread对象并调用thread.interrupt()

0

让其他线程定期检查一个布尔标志(isCancelled,或类似的东西)。最初是错误的。

从您的停止按钮代码,将此值设置为true。

当您的线程接下来检查标志并发现它为真时,线程应该自行终止。

+1

从外部调用'interrupt()',然后使用'isInterrupted()'进行检查就像设置自己的标志一样。另外它的优点是可以唤醒睡眠线,以便及时结束。 – 2011-03-21 21:04:05

+0

@Ted - 我以前一直觉得可能会有线程被任意中断(这会使这种方法不安全) - 我误解了吗? – Cephron 2011-03-21 21:07:15

+0

你错了。 'Thread.interrupt()'不会任意中断一个线程。事实上,它*只会*中断*一些*阻止库调用。其余的,它只是设置一个标志。 – 2011-03-21 21:16:31

2

你有几个选择,它们取决于你如何定义线程的各种状态。

线程在退出run()方法时有效停止。

要“暂停”和“恢复”线程的执行,您可以使用wait()和notify()。

为了说明这一点,这里有一个简单的例子:

class MyThread implements Runnable { 
    private boolean keepRunning = false; 
    private boolean isPaused = false; 

    public void run() { 
     keepRunning = true; 
     try { 
      while (keepRunning) { 
       // do stuff here 
       if (isPaused) { 
        synchronized (this) { 
         // wait for resume() to be called 
         wait(); 
         isPaused = false; 
        } 
       } 
      } 
     } catch (Exception ex) { 
      // do stuff 
     } 
    } 

    // note that as-is this won't do anything to a paused thread until 
    // it is resumed. 
    public void stop() { 
     keepRunning = false; 

    } 

    public void pause() { 
     isPaused = true; 
    } 

    public synchronized void resume() { 
     // notify anybody waiting on "this" 
     notify(); 
    } 
} 
+4

在上面的代码中还要记住一点:pause()和stop()方法是非阻塞调用,因此它们会立即返回。您可以通过使用等待和通知来阻止呼叫。也取决于你在主循环中做什么,线程可能永远不会暂停或停止。这是在socket.accept没有超时设置的套接字服务器的初学者实现中的一个常见错误。 – Nick 2011-03-21 21:11:20

+0

我不认为这是正确的方式来调用通知,因为我得到这个错误 - > 03-22 14:17:53.328:错误/ AndroidRuntime(2628):java.lang.IllegalMonitorStateException: 03-22 14:17:53.328:ERROR/AndroidRuntime(2628):at java.lang.Object.notify(Native Method) – abhishek 2011-03-22 08:50:42

+0

你是从同步方法还是同步块中调用notify()?如果没有,你会得到这个消息。 – Nick 2011-03-22 16:40:18

2

要控制Java线程,你应该补充的方法,可以通过设置你的run()方法来读取变量其他对象调用的对象。你不给你在做什么太多的信息,但这里有一个可能的模式:

public class ProgressBarUpdater implements Runnable{ 
    private volatile boolean paused = false; 
    private volatile boolean finished = false; 

    /* other fields, constructor etc. */ 

    public void run(){ 
     while(!finished){ 
      updateProgressBar(); 

      while(paused && !finished){ 
       try{ 
        Thread.sleep(1000); //Busy wait - should really use wait/notify, but that's another lesson 
       } 
       catch(InterruptedException e){ 

       } 
      } 
     } 
    } 

    public synchronized void pauseProgressBar(){ 
     paused = true; 
    } 

    public synchronized void unPauseProgressBar(){ 
     paused = false; 
     //call notify() here when you switch to wait/notify. 
    } 

    public void stopProgressBar(){ 
     finished = true; 
     //call notify() here too. 
    } 
} 

你可能会想用周围的控制变量更强大的同步,并且,如在评论中提到的,等待/通知而不是忙碌的等待。

使用像这样:

ProgressBarUpdater pbu = new ProgressBarUpdater(); 

Thread t = new Thread(pbu); 

t.start(); 
Thread.sleep(10000); //let the progress bar run for ten seconds. 

pbu.pauseProgressBar(); 
Thread.sleep(10000); //pause it for ten seconds. 

pbu.unPauseProgressBar(); 
Thread.sleep(10000); //restart for another ten seconds. 

pbu.stopProgressBar(); //stop progress bar. 
+0

嘿感谢您的支持,但是当我试图停止与您的代码的线程我得到03-22 14:17:53.328:错误/ AndroidRuntime(2628):java.lang.IllegalMonitorStateException:对象未通过线程锁定通知) 03-22 14:17:53.328:ERROR/AndroidRuntime(2628):at java.lang.Object.notify(Native Method) 错误 – abhishek 2011-03-22 08:50:07