2014-09-24 80 views
0

我正在用eclipse中窗口生成器的幫助創建一個GUI,創建一個簡單的java程序。該GUI由一個按鈕組成。Java線程啓動 - 停止啓動在Eclipse中點擊相同的按鈕

我的目標: - 點擊按鈕後,啓動一個線程,無限次地打印到控制檯號碼,直到再次單擊相同的按鈕來停止。

這裏是我的實現: -

Runner.java(Thread類)

public class Runner extends Thread{ 

    private volatile boolean running = true; 
    private int i = 1; 

    @Override 
    public void run() { 

     while(running) 
     { 
      System.out.println(i++ +"\n"); 
      try { 
       sleep(1000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 



    public void shutdown() 
    { 
     running = false; 
    } 

} 

MainGUI.java(ui類)

Runner runIT = new Runner(); 
final JButton btnNewButton = new JButton("Start Thread"); 
     btnNewButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 

       String buttonText = btnNewButton.getText(); 
       if(buttonText.equals("Start Thread")) 
       { 
        btnNewButton.setText("Stop Thread"); 
        runIT.start(); 
       } 

       else if(buttonText.equals("Stop Thread")) 
       { 
        btnNewButton.setText("Start Thread"); 
        runIT.shutdown(); 

       } 
      } 
     }); 

我的問題: - 線程開始和停止完美,但只是一次。也就是說,我只能啓動和停止線程一次。當我嘗試重新啓動停止的線程時,它會失敗。 我希望線程繼續從停止的相同值打印數字。

Error :- Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException 
    at java.lang.Thread.start(Thread.java:705) 
    at com.zakoi.java.thread.GUI.MainGUI$2.actionPerformed(MainGUI.java:62) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) 
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) 
    at java.awt.Component.processMouseEvent(Component.java:6516) 
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3311) 
    at java.awt.Component.processEvent(Component.java:6281) 
    at java.awt.Container.processEvent(Container.java:2229) 
    at java.awt.Component.dispatchEventImpl(Component.java:4872) 
    at java.awt.Container.dispatchEventImpl(Container.java:2287) 
    at java.awt.Component.dispatchEvent(Component.java:4698) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832) 
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492) 
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422) 
    at java.awt.Container.dispatchEventImpl(Container.java:2273) 
    at java.awt.Window.dispatchEventImpl(Window.java:2719) 
    at java.awt.Component.dispatchEvent(Component.java:4698) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735) 
    at java.awt.EventQueue.access$200(EventQueue.java:103) 
    at java.awt.EventQueue$3.run(EventQueue.java:694) 
    at java.awt.EventQueue$3.run(EventQueue.java:692) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) 
    at java.awt.EventQueue$4.run(EventQueue.java:708) 
    at java.awt.EventQueue$4.run(EventQueue.java:706) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91) 

請幫忙。

+0

您不能再次啓動停止的線程。在「開始」上創建一個新實例。閱讀JavaDoc瞭解更多詳情:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#start%28%29 – Tom 2014-09-24 07:54:08

回答

0

多次啓動線程永遠不合法。特別是,線程一旦完成執行就不會重新啓動。

- 從Thread API

+0

: - 假設我想繼續從相同的打印線程停止的號碼..我該如何去做呢? – saugatchetry 2014-09-24 07:59:47

+0

你將需要一個_thread-safe_方法來在你的'Runner'類關閉後檢索一個值(一個'volatile int'是一種可能性,但不一定是最好的),而_thread-safe_意味着初始化下一個_新_'亞軍'在你開始之前。 – 2014-09-24 08:02:08

0

首先從未手寫GUI代碼,有大量的真棒工具生成完美組織模塊化和可讀的代碼。我個人的最愛是如果它的Swing:Netbeans GUI構建器,如果它的JavaFX(與Swing相比非常棒),那麼它的SceneBuilder又由Oracle提供支持和提供。

其次也是最重要的主題,可以只啓動一次......所以一定要確保你的代碼doesent嘗試再次啓動它...這就是爲什麼你會得到IllegalStateException異常,因爲線程實例執行已經完成...

另外線程是重對象,應該小心創建這些對象,在你的情況下,它當然可以,但通常它有很好的線程池和重用線程......總是避免手動創建線程,因爲你必須正確地跟蹤它們完成後,如果你留下任何非deamon線程活着你的應用程序不會完成其執行...

0

一個簡單的解決方案草圖:

  • 您的類並不需要延長Thread,簡單地實現Runnable
  • 當聽按鈕事件,首先要確保你的反應只在你真的想
  • 這些事件在你ActionListener,創建一個新的要啓動一個每次螺紋,帶您Runnable對象初始化,並調用Thread.start()
1

你應該有線程運行,但充當服務。然後應該通過某種形式的溝通來控制它。

創建線程非常昂貴 - 它們不應該被不必要地創建/銷燬。

此代碼使用鎖來實現可以暫停和恢復的Thread。這裏有一些比你想要的更多,但它展示了理論。

/** 
* PauseableThread is a Thread with pause/resume and cancel methods. 
* 
* The meat of the process must implement `step`. 
* 
* You can either extend this and implement `step` or use the factory. 
* 
* I cannot extend Thread because my resume will clash. 
* 
*/ 
public abstract class PauseableThread implements Runnable { 

    // The lock. 

    private final ReadWriteLock pause = new ReentrantReadWriteLock(); 
    private final Lock readLock = pause.readLock(); 
    private final Lock writeLock = pause.writeLock(); 
    // Flag to cancel the wholeprocess. 
    private volatile boolean cancelled = false; 
    // The exception that cause it to finish. 
    private Exception thrown = null; 
    // The thread that is me. 
    private Thread me = null; 

    @Override 
    // The core run mechanism. 
    public void run() { 
     // Track my current thread. 
     me = Thread.currentThread(); 
     try { 
      while (!finished()) { 
       // Block here if we're paused. 
       blockIfPaused(); 
       // Don't do any more work if we've been asked to stop. 
       if (!finished()) { 
        // Do my work. 
        step(); 
       } 
      } 
     } catch (Exception ex) { 
      // Just fall out when exception is thrown. 
      thrown = ex; 
     } 
    } 

    // Have we finished yet? 
    private boolean finished() { 
     return cancelled || !me.isInterrupted(); 
    } 

    // Block if pause has been called without a matching resume. 
    private void blockIfPaused() throws InterruptedException { 
     try { 
      // Grab a write lock. Will block if a read lock has been taken. 
      writeLock.lockInterruptibly(); 
     } finally { 
      // Release the lock immediately to avoid blocking when pause is called. 
      writeLock.unlock(); 
     } 
    } 

    // Pause the work. NB: MUST be balanced by a resume. 
    public void pause() { 
     // We can wait for a lock here. 
     readLock.lock(); 
    } 

    // Resume the work. NB: MUST be balanced by a pause. 
    public void resume() { 
     // Release the lock. 
     readLock.unlock(); 
    } 

    // Stop. 
    public void cancel() { 
     // Stop everything. 
     cancelled = true; 
    } 

    // Stop immediately (if param is true). 
    public void cancel(boolean interrupt) { 
     if (interrupt) { 
      // Interrupt me. 
      me.interrupt(); 
     } else { 
      // Or cancel me. 
      cancel(); 
     } 
    } 

    // Wait for completion. 
    public void await() throws InterruptedException { 
     // Wait 'till we've finished. NB: Will wait forever if you haven't instigated a cancel of some kind. 
     while (me.isAlive()) { 
      Thread.sleep(0); 
     } 
    } 

    // Start - like a thread. 
    public void start() { 
     // Wrap me in a thread and fire the sucker up! 
     new Thread(this).start(); 
    } 

    // Get the exception that was thrown to stop the thread or null if the thread was cancelled. 
    public Exception getThrown() { 
     return thrown; 
    } 

    // Expose my Thread. 
    public Thread getThread() { 
     return me; 
    } 

     // Create this method to do stuff. 
    // Calls to this method will stop when pause is called. 
    // Any thrown exception stops the whole process. 
    public abstract void step() throws Exception; 

    // Factory to wrap a Stepper in a PauseableThread 
    public static PauseableThread make(Stepper stepper) { 
     StepperThread pauseableStepper = new StepperThread(stepper); 
     // That's the thread they can pause/resume. 
     return pauseableStepper; 
    } 

    // One of these must be used. 
    public interface Stepper { 

     // A Stepper has a step method. 
     // Any exception thrown causes the enclosing thread to stop. 

     public void step() throws Exception; 
    } 

    // Holder for a Stepper. 
    private static class StepperThread extends PauseableThread { 

     // The actual stepper I am proxying. 

     private final Stepper stepper; 

     StepperThread(Stepper stepper) { 
      this.stepper = stepper; 
     } 

     @Override 
     public void step() throws Exception { 
      stepper.step(); 
     } 
    } 

     // !!!! Testing only below !!!! 
    // My test counter. 
    static int n = 0; 

    // Test/demo. 
    public static void main(String[] args) throws InterruptedException { 

     try { 
      // Simple stepper that just increments n. 
      Stepper s =() -> { 
       n += 1; 
       Thread.sleep(1); 
      }; 
      PauseableThread pt = PauseableThread.make(s); 
      // Start it up. 
      pt.start(); 
      Thread.sleep(1000); 
      pt.pause(); 
      System.out.println("Paused: " + n); 
      Thread.sleep(1000); 
      System.out.println("Resuminng: " + n); 
      pt.resume(); 
      Thread.sleep(1000); 
      pt.cancel(); 
      System.out.println("Finished: " + n); 

      // Start again to test agressive cancelling. 
      pt.await(); 
      n = 0; 
      pt = PauseableThread.make(s); 
      // Start it up. 
      pt.start(); 
      Thread.sleep(1000); 
      pt.pause(); 
      System.out.println("Paused: " + n); 
      Thread.sleep(1000); 
      System.out.println("Resuminng: " + n); 
      pt.resume(); 
      Thread.sleep(1000); 
      // Cancel aggressively. 
      pt.cancel(true); 
      System.out.println("Finished: " + n); 
      System.out.println("thrown: " + pt.getThrown()); 

     } catch (InterruptedException e) { 
     } 
    } 
} 
相關問題