-1

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

“Reader” Thread -reader 在找到目标 # 并正确显示时间时停止。

"Writer" Thread -writer 使用最大 # 生成随机数。

我真正的问题是如何将这两个线程与此混合,我已经尝试添加睡眠、中断、通知、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;
        }*/
     }
   });
}
}
4

1 回答 1

2

这是我第一次做多线程,我有点纠结于如何让两个线程,“Reader”线程和“Writer”线程仅在单击 JButton“jbStart”时执行?

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

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

这称为创建SSCCE。然后,如果它仍然不起作用,您可以在论坛上发布简单的代码。我们没有时间通读您的所有代码来查看您在做什么。

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

运行不正确是什么意思?如果它不起作用,那么您没有正确实现线程。我们不知道您要做什么,因此无法提供具体建议。

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

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

于 2013-06-15T04:26:28.743 回答