2016-04-23 38 views
0

我有一個程序可以估計每百萬次試驗的PI值。但是,我希望程序在點擊暫停時恢復,並在點擊運行時恢復,使用wait()notify()我想暫停並恢復我的程序

我必須使用多個線程以及Boolean作爲它應該暫停和運行的信號,但我不知道如何。我很困惑。

任何想法?

package com.company; 

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

public class Ex03 extends JFrame implements Runnable, ActionListener { 
    int n = 0; 
    int c = 0; 
    double Pi; 
    int change = 1000000; 
    boolean runing = true; 

    JLabel actualpi = new JLabel("The Actual value of PI " + Math.PI); 
    JLabel estimation = new JLabel("Current Estimate: "); 
    JLabel tri = new JLabel("Number Of Trials: " + n); 
    JButton run = new JButton("Run"); 
    JButton pause = new JButton("Pause"); 

    public Ex03() { 
     super("Ex 03"); 
     setLayout(new GridLayout(4, 1)); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(400, 400); 
     setVisible(true); 
     add(actualpi); 
     add(estimation); 
     add(tri); 
     add(run); 

     run.addActionListener(this); 
     pause.addActionListener(this); 
    } 

    public void actionPerformed(ActionEvent e) { 
     Thread thread = new Thread(this); 
     if (e.getSource() == run) { 
      thread.start(); 
      remove(run); 
      add(pause); 
     } else if (e.getSource() == pause) { 
      remove(pause); 
      add(run); 
      try { 
       thread.wait(); 
      } catch (InterruptedException e1) { 
      } 
     } 
    } 

    public void run() { 
     n++; 
     while (runing) { 
      double x = Math.random(); 
      double y = Math.random(); 
      if (((x * x) + (y * y)) <= 1) 
       c++; 
      n++; 
      Pi = (4.0 * (double) c/n); 

      if (n == change) { 
       estimation.setText("Current Estimate: " + Pi); 
       tri.setText("Number Of Trials: " + n); 
       change = change + 1000000; 
      } 

      try { 
       Thread.sleep(0); 
      } catch (InterruptedException e) { 
      } 
     } 
    } 

    public static void main(String[] args) { 
     new Ex03(); 
    } 
} 
+0

你不應該使用等待和通知。他們太低級,很難很好地使用。使用更高級別的抽象:從鎖創建的條件。閱讀javadoc的例子。請注意,你的'runing'標誌應該是揮發性的。而且它沒用,因爲你可以使用interrupt()來中斷線程。再次,閱讀javadoc。併發性是一個非常困難的話題。我建議你在實踐中閱讀Java併發,因爲你的簡單例子表明你錯過了很多東西。 –

+0

在你甚至是監聽器的內部,你每次用戶按下按鈕時都會創建* new *線程對象。如果您想訪問已經創建的線程來暫停它,這將不起作用。在類的構造函數中只創建一次線程並將其保存到字段中,然後在該字段上使用'wait'' notify'。 – csharpfolk

回答

0

下面是例子,如何用旗語做,在控制檯應用程序:

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.Semaphore; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     PiThread piThread = new PiThread(); 
     piThread.start(); 

     BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in)); 
     String cmd; 
     while ((cmd = bufferRead.readLine()) != null) { 
      System.out.println("write p to pause, r to resume, s to stop"); 

      switch (cmd) { 
       case "p": 
        piThread.pauseComputation(); 
        break; 

       case "r": 
        piThread.resumeComputation(); 
        break; 

       case "s": 
        piThread.stopComputation(); 
        piThread.join(); 
        return; 
      } 
     } 
    } 

    public static class PiThread extends Thread { 
     private volatile boolean stop = false; 

     private volatile int total = 0; 
     private volatile int insideCircle = 0; 
     private Semaphore semaphore = new Semaphore(1, true); 

     @Override 
     public void run() { 
      while (!stop) { 

       for (int i = 0; i < 1000; i++) { 
        double x = Math.random(); 
        double y = Math.random(); 

        if (((x * x) + (y * y)) <= 1) 
         insideCircle++; 

        total++; 
       } 

       // using semaphores is slow 
       try { 
        // not to garbage stdout 
        Thread.sleep(100); 

        semaphore.acquire(); 
        semaphore.release(); 
       } 
       catch (InterruptedException e) { 
        // exit 
        return; 
       } 

       System.out.println("pi: " + getPiApproximation()); 
       System.out.flush(); 
      } 
     } 

     public void pauseComputation() { 
      try { 
       semaphore.acquire(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

     public void resumeComputation() { 
      semaphore.release(); 
     } 

     public void stopComputation() { 
      stop = true; 
     } 

     public double getPiApproximation() { 
      return 4*(double)insideCircle/(double)total; 
     } 
    } 
} 

它可能不是在GUI處理的最佳方式,但會給你一個良好的開端。主要想法是使用Semaphore來阻止工作線程。爲了這個工作,你必須在resumeComputation之前總是調用pauseComputation,否則會出現死鎖。在您調用stopComputation之後,您無法恢復計算或暫停計算。