如何在GUI的actionPerformed()方法中运行线程run()?

时间:2013-06-15 04:16:14

标签: java multithreading swing concurrency interrupt-handling

这是我第一次做多线程而且我有点坚持如何创建两个线程,“Reader”线程和“Writer”线程只在单击JButton“jbStart”时执行?我不能把run()方法放在actionPerformed()中,因为它不会正确运行,我也不能在其中添加thread.start(),它必须是一个静态的main方法,除非我'我错了纠正我。现在,整个代码按原样运行。为了进一步了解,它只是一个Target Finder程序,您可以在其中输入Max#(要生成的最大随机数 - 例如:Max#= 100,随机数将生成0到100之间的任何值),Target #(要查找的目标编号以及在ms中花费的时间。)缓冲区只读取JTextArea。

“读者”主题 -reader在找到目标#时停止并正确显示时间。

“作家”主题 -writer使用max#。

生成随机数

我真正的问题是我如何将这两个线程混合在一起,我已经尝试过添加sleep,interrupt,notify,signalAll等...但是我只是不知道该把它放到哪里才能让它正常工作。希望你们能告诉我这个程序是如何工作的,我很乐意从中学习并掌握线程如何工作的知识。这是代码:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class TargetFinder extends JFrame implements ActionListener
{
//GUI attributes
JLabel jlMax, jlTarget, jlBuffer;
JTextField jtfMax, jtfTarget, jtfBuffer;
JTextArea txtArea;
JScrollPane jsp;
JButton jbStart, jbReset, jbExit;
JPanel pnl1, pnl2, nPnl, sPnl;
int isIntegerMax, isIntegerTarget;
String isStringMax, isStringTarget;

public TargetFinder()
{
  //create frame
  setLayout(new BorderLayout());

  //create content
  /*-------------------------------NORTH-------------------------------*/

  jlMax = new JLabel("Max #");
  jtfMax = new JTextField(7);

  jlTarget = new JLabel("Target #");
  jtfTarget = new JTextField(7);

  jlBuffer = new JLabel("Buffer");
  jtfBuffer = new JTextField(7);
  jtfBuffer.setEditable(false);

  //create panel and add contents to it
  pnl1 = new JPanel();
  pnl1.add(jlMax);
  pnl1.add(jtfMax);
  pnl1.add(jlTarget);
  pnl1.add(jtfTarget);
  pnl1.add(jlBuffer);
  pnl1.add(jtfBuffer);

  nPnl = new JPanel();
  nPnl.add(pnl1);

  add(nPnl,"North"); //add the panel to the North on the JFrame

  /*-------------------------------CENTER-------------------------------*/

  txtArea = new JTextArea(25,60);
  txtArea.setLineWrap(true);
  txtArea.setWrapStyleWord(true);
  txtArea.setEditable(true);
  jsp = new JScrollPane(txtArea);
  jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
  jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

  add(jsp,"Center"); //add JScrollPane to the JTextArea where as-is

  /*-------------------------------SOUTH-------------------------------*/

  jbStart = new JButton("Start");
  jbStart.setMnemonic('S');

  jbReset = new JButton("Reset");
  jbReset.setMnemonic('R');

  jbExit = new JButton("Exit");
  jbExit.setMnemonic('x');

  //create panel and add contents to it
  pnl2 = new JPanel();
  pnl2.add(jbStart);
  pnl2.add(jbReset);
  pnl2.add(jbExit);

  sPnl = new JPanel();
  sPnl.add(pnl2);

  add(sPnl, "South"); //add the panel to the South on the JFrame

  //ActionListener Registration
  //jtfMax.addActionListener(this);
  //jtfTarget.addActionListener(this);
  //jtfBuffer.addActionListener(this);
  jbStart.addActionListener(this);
  jbReset.addActionListener(this);
  jbExit.addActionListener(this);

  //GUI properties
  setTitle("Target Finder");
  setLocation(200,200);
  setSize(700,500);
  setVisible(true);
  setDefaultCloseOperation(EXIT_ON_CLOSE);
  pack(); //resize window to fit
}

public void actionPerformed(ActionEvent ae)
{
  //checks user input of jtfMax and jtfTarget
  if(ae.getSource() == jbStart)
  {
     /*------------------------MAX #------------------------*/
     try
     {
        isStringMax = jtfMax.getText(); //get the text of Max #
        isIntegerMax = 0;

        isIntegerMax = Integer.parseInt(isStringMax); //convert from String to int

        if(isIntegerMax < 0) //if the value is negative
        {
           JOptionPane.showMessageDialog(null,"Please enter a positive number", "Max #", JOptionPane.INFORMATION_MESSAGE);
        }
     }
     catch(NumberFormatException nfe)
     {
        if(jtfMax.getText().isEmpty())
        {
           JOptionPane.showMessageDialog(null,"Please enter a positive number", "Max #", JOptionPane.INFORMATION_MESSAGE);
        }
        else
        {
           JOptionPane.showMessageDialog(null,"You entered: " + isStringMax + "\nPlease enter a positive number", 
           "Max #", JOptionPane.INFORMATION_MESSAGE);
        }
     }

     /*------------------------TARGET #------------------------*/
     try
     {
        isStringTarget = jtfTarget.getText(); //get the text of Target #
        isIntegerTarget = 0;

        isIntegerTarget = Integer.parseInt(isStringTarget); //convert from String to int

        if(isIntegerTarget < 0) //if the value is negative
        {
           JOptionPane.showMessageDialog(null,"Please enter a positive number", 
           "Target #", JOptionPane.INFORMATION_MESSAGE);
        }
     }
     catch(NumberFormatException nfe)
     {
        if(jtfTarget.getText().isEmpty())
        {
           JOptionPane.showMessageDialog(null,"Please enter a positive number", "Target #", JOptionPane.INFORMATION_MESSAGE);
        }
        else
        {
           JOptionPane.showMessageDialog(null,"You entered: " + isStringTarget + "\nPlease enter a positive number", 
           "Target #", JOptionPane.INFORMATION_MESSAGE);
        }
     }

     try
     {
        if(isIntegerTarget >= isIntegerMax || isIntegerTarget < 0) //if Target # >= Max # (>= avoids a glitch where it freezes the program if Max # = Target #)
        {
           JOptionPane.showMessageDialog(null,"Please enter a target number < Max #");
        }
        else
        {
           //checks both values if can be converted to an int
           Integer.parseInt(isStringMax);
           Integer.parseInt(isStringTarget);

           try
           {
              Random randomGenerator = new Random(); //create a random object for random numbers
              Boolean foundMatch = false; //check when random numbers = Target #

              final long startTime = System.currentTimeMillis(); //start of the program's execution time in milliseconds
              //generates many random numbers until condition is met
              while(!foundMatch)
              {
                 int randomInt = randomGenerator.nextInt(isIntegerMax); //generates random numbers up to the value of Max # (isIntegerMax)
                 String isStringRandom = Integer.toString(randomInt); //convert random numbers to String
                 txtArea.append(randomInt + " "); //add random numbers to the JTextArea

                 String isBuffer = Integer.toString(randomInt); //convert randomInt int to String
                 jtfBuffer.setText(isBuffer);

                 String isStringTarget = Integer.toString(isIntegerTarget); //convert Target # (isIntegerTarget) to String

                 //if the Buffer matches the Target #
                 if(isBuffer.equals(isStringTarget))
                 {
                    foundMatch = true;
                    break;
                 }
              }
              final long duration = System.currentTimeMillis() - startTime; //calculate the total time of the program's execution
              txtArea.append("\nIt took " + duration + " milliseconds");
              txtArea.requestFocus();
           }
           catch(IllegalArgumentException iae)
           {
              iae.printStackTrace(); //prints the error messages
              return;
           }
        }
     }
     catch(NumberFormatException nfe)
     {
        JOptionPane.showMessageDialog(null, "Either Max # and/or Target # is not a number. Please enter a positive number");
     }
  }
  else if(ae.getSource() == jbReset)
  {
     //empty all text fields
     jtfMax.setText("");
     jtfTarget.setText("");
     jtfBuffer.setText("");
     txtArea.setText("");
     jtfMax.requestFocus();
  }
  else if(ae.getSource() == jbExit)
  {
     System.exit(0);
  }
}

/**
  This class implements the first runnable object for the first thread
*/
class Runnable1 implements Runnable
{
  public synchronized void run()
  {
     try
     {
        Thread.sleep(1);
     }
     catch(InterruptedException ie)
     {
        System.out.println("Reader Thread #1 Interrupted!");
     }
  }
}

/**
  This class implements the second runnable object for the second thread
*/
class Runnable2 implements Runnable
{
  public synchronized void run()
  {
     try
     {
        Thread.sleep(1);
         /*------------------------BUFFER------------------------*/

        //String isBuffer = Integer.toString(isIntegerTarget); //convert Target # int to String
        //jtfBuffer.setText(isBuffer);

        /*------------------------RANDOM NUMBER GENERATOR------------------------*/

        /*READER THREAD HANDLES THIS*/

        /*WRITER THREAD HANDLES THIS*/


        /*
        try
        {
           if(isIntegerTarget >= isIntegerMax) //if Target # >= Max # (>= avoids a glitch where it freezes the program if Max # = Target #)
           {
              JOptionPane.showMessageDialog(null,"Please enter a target number < Max #");
           }
           else
           {
              //checks both values if can be converted to an int
              Integer.parseInt(isStringMax);
              Integer.parseInt(isStringTarget);

              try
              {
                 Random randomGenerator = new Random(); //create a random object for random numbers
                 Boolean foundMatch = false; //check when random numbers = Target #

                 final long startTime = System.currentTimeMillis(); //start of the program's execution time in milliseconds
                 //generates many random numbers until condition is met
                 while(!foundMatch)
                 {
                    int randomInt = randomGenerator.nextInt(isIntegerMax); //generates random numbers up to the value of Max # (isIntegerMax)
                    String isStringRandom = Integer.toString(randomInt); //convert random numbers to String
                    txtArea.append(randomInt + " "); //add random numbers to the JTextArea

                    String isBuffer = Integer.toString(randomInt); //convert randomInt int to String
                    jtfBuffer.setText(isBuffer);

                    String isStringTarget = Integer.toString(isIntegerTarget); //convert Target # (isIntegerTarget) to String

                    //if the Buffer matches the Target #
                    if(isBuffer.equals(isStringTarget))
                    {
                       foundMatch = true;
                       break;
                    }
                 }
                 final long duration = System.currentTimeMillis() - startTime; //calculate the total time of the program's execution
                 txtArea.append("\nIt took " + duration + " milliseconds");
                 txtArea.requestFocus();
              }
              catch(IllegalArgumentException iae)
              {
                 iae.printStackTrace(); //prints the error messages
                 return;
              }
           }
        }
        catch(NumberFormatException nfe)
        {
           JOptionPane.showMessageDialog(null, "Either Max # and/or Target # is not a number. Please enter a positive number");
        }
        */

     }
     catch(InterruptedException ie)
     {
        System.out.println("Writer Thread #2 Interrupted!");
     }
  }
}

public static void main(String[] args)
{
  SwingUtilities.invokeLater(new Runnable() 
  {
     @Override
     public void run() 
     {
        // create the window
        TargetFinder targetFinder = new TargetFinder(); //runs the program

        // create the writer thread
        Runnable r1 = targetFinder.new Runnable1();
        Thread t1 = new Thread(r1);

        // create the reader thread
        Runnable r2 = targetFinder.new Runnable2();
        Thread t2 = new Thread(r2);


        // start the threads
        t1.start();
        t2.start();
        /*try
        {
        }
        catch(InterruptedException ie)
        {
           ie.printStackTrace();
           return;
        }*/
     }
   });
}
}

1 个答案:

答案 0 :(得分:2)

  

这是我第一次做多线程而且我有点坚持如何创建两个线程,“Reader”线程和“Writer”线程只在单击JButton“jbStart”时执行?

那你为什么要写一个300行程序来测试呢?

为什么不从包含单个JButton的GUI开始,该JButton称为“Start”,在单击时启动Thread。一旦你开始工作,你就可以对你的真实程序进行更改。

这称为创建SSCCE。然后,如果它仍然无法正常工作,您可以在论坛上发布简单的代码。我们没有时间阅读您的所有代码,看看您在做什么。

  

我不能把run()方法放在actionPerformed()中,因为它不能正确运行

什么不能正确运行?如果它不起作用,那么你没有正确实现Thread。我们不知道您的尝试是什么,所以我们无法给出具体的建议。

  

我也不能在其中添加thread.start(),它必须是一个静态的main方法,除非我错了纠正我

您不应该使用静态方法。只需将Runnable创建为类变量即可。然后,您可以从类中的任何位置调用start()方法。或者在actionPerformed()方法中定义整个Runnable。