2016-04-23 18 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'フラグは動作するようにvolatileでなければならないことに注意してください。また、スレッドを中断するためにinterrupt()を使用するだけで済むので、無駄です。再度、javadocを読んでください。並行処理は非常に困難なトピックです。実際にはJavaの並行処理を読むことをお勧めします。単純な例では、たくさんのものが足りないことが示されているからです。 –

+0

あなたもリスナーの中に、ユーザーがボタンを押すたびに*新しい*スレッドオブジェクトを作成しています。これは、既に作成されたスレッドにアクセスして一時停止する場合には機能しません。クラスコンストラクタでスレッドを1回だけ作成してフィールドに保存し、そのフィールドに '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でこれを処理するための最良の方法ではないかもしれないが、あなたは良いスタートを与えます。主なアイデアは、セマフォを使用してワーカースレッドをブロックすることです。これが機能するには、resumeComputationの前に必ずpauseComputationを呼び出す必要があります。それ以外の場合は、デッドロックが発生します。 stopComputationを呼び出した後、ResumeComputationまたはpauseComputationを再開することはできません。

関連する問題