在循环中无法按下 JButton
Can't press JButton while in loop
我正在尝试制作一个程序,在用户按下按钮时生成随机数。它应该停止生成它们,当用户第二次按下按钮时,然后它应该打印所有加在一起的随机数和平均随机数,但我不知道我应该怎么做。当我在循环中时,我无法按下按钮。我会感谢任何帮助。我的代码:
package Test;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Average
{
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = true;
static JButton b1 = new JButton("Click me");
static void JFrame()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
JFrame f = new JFrame("Test");
f.setSize(sizeX, sizeY);
f.setVisible(true);
f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
f.setResizable(false);
f.setAutoRequestFocus(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(b1);
}
static void ActionListener()
{
b1.addActionListener(new ActionListener()//ActionListener
{
public void actionPerformed(ActionEvent e)//Execute when button is pressed
{
int numsGenerated = 0;
double ave = 0;
if (running == true)
{
while (true)
{
double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
numsGenerated++;
ave = ave + r;
System.out.println("Random: " + r);
if (!running)
{
break;
}
}
running = false;
}
else
{
System.out.println("");
System.out.println("All: " + ave);
System.out.println("Average: " + ave / numsGenerated);
running = true;
}
}
}); //ActionListenerEnd
}
public static void main(String[] args)//Main
{
JFrame();
ActionListener();
}
}
正如 Ordous 在评论中所说,你应该为这项工作创建一个不同的线程。但是您可能需要同步 "running" 变量以确保它始终有效。
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Average
{
static Object lock=new Object();
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = false;
static JButton b1 = new JButton("Click me");
static void JFrame()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
JFrame f = new JFrame("Test");
f.setSize(sizeX, sizeY);
f.setVisible(true);
f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
f.setResizable(false);
f.setAutoRequestFocus(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(b1);
}
public class Thr extends Thread
{
@Override
public void run()
{
int numsGenerated = 0;
double ave = 0;
synchronized(lock)
{
running=!running;
}
if (running == true)
{
while (true)
{
double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
numsGenerated++;
ave = ave + r;
System.out.println("Random: " + r);
synchronized(lock)
{
if (!running)
{
break;
}
}
}
synchronized(lock)
{
running = false;
}
}
System.out.println("");
System.out.println("All: " + ave);
System.out.println("Average: " + ave / numsGenerated);
running = true;
}
}
static Thr thread=null;
static void ActionListener()
{
b1.addActionListener(new ActionListener()//ActionListener
{
public void actionPerformed(ActionEvent e)//Execute when button is pressed
{
Average av=new Average();
if(thread==null)
{
thread=av.new Thr(); // should add in an executor
thread.start();
}
else
{
synchronized(lock)
{
running=false;
}
}
}
}); //ActionListenerEnd
}
public static void main(String[] args)//Main
{
JFrame();
ActionListener();
}
}
要有一个简单的线程,"Thread" 被继承并且 运行() 方法必须被覆盖才能使用它。 (你也可以使用 "Runnable" 而不是这个)
public class Thr extends Thread
{
@Override
public void run()
{
}
}
你开始喜欢
threadName.Start()
或
ExecutorObject.submit(threadName);
其中执行器对象有一个线程池,可以有效地 运行 并由执行器服务创建。
不要以
开始线程
threadname.run()
直接。
线程间通信也很重要。一个线程向某处留言,另一个线程读取。如果没有同步,它们可能会争夺变量的可见性,并可能发生错误的输出。
您可以锁定一个对象。
synchronized(lock)
{
}
所以这个块只能由单个线程进入,直到它退出这个块。你应该给其他线程留言,说 "its ready" 并用
唤醒它们(如果它们正在等待)
synchronized(lock)
{
lock.notifyAll();
}
然后让消息离开线程(当前线程)进入等待状态,以便其他线程可以唤醒它并让它退出块。
synchronized(lock)
{
lock.notifyAll();
lock.wait();
}
但这还不够,因为当前线程不小心退出了等待状态,所以你可以强制它继续等待:
synchronized(lock)
{
lock.notifyAll();
while(condition)
lock.wait();
}
如果您确保一次只有一个线程可以访问一个变量,您可以使用它与其他线程通信。
您可以使用其他一些方法来设置障碍以同步某个点上的所有线程,这样在所有线程都遇到相同的障碍之前,任何线程都无法继续。更多的沟通会降低整体性能。
主程序也是线程,可以等待,通知,同步。
我正在尝试制作一个程序,在用户按下按钮时生成随机数。它应该停止生成它们,当用户第二次按下按钮时,然后它应该打印所有加在一起的随机数和平均随机数,但我不知道我应该怎么做。当我在循环中时,我无法按下按钮。我会感谢任何帮助。我的代码:
package Test;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Average
{
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = true;
static JButton b1 = new JButton("Click me");
static void JFrame()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
JFrame f = new JFrame("Test");
f.setSize(sizeX, sizeY);
f.setVisible(true);
f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
f.setResizable(false);
f.setAutoRequestFocus(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(b1);
}
static void ActionListener()
{
b1.addActionListener(new ActionListener()//ActionListener
{
public void actionPerformed(ActionEvent e)//Execute when button is pressed
{
int numsGenerated = 0;
double ave = 0;
if (running == true)
{
while (true)
{
double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
numsGenerated++;
ave = ave + r;
System.out.println("Random: " + r);
if (!running)
{
break;
}
}
running = false;
}
else
{
System.out.println("");
System.out.println("All: " + ave);
System.out.println("Average: " + ave / numsGenerated);
running = true;
}
}
}); //ActionListenerEnd
}
public static void main(String[] args)//Main
{
JFrame();
ActionListener();
}
}
正如 Ordous 在评论中所说,你应该为这项工作创建一个不同的线程。但是您可能需要同步 "running" 变量以确保它始终有效。
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Average
{
static Object lock=new Object();
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = false;
static JButton b1 = new JButton("Click me");
static void JFrame()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
JFrame f = new JFrame("Test");
f.setSize(sizeX, sizeY);
f.setVisible(true);
f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
f.setResizable(false);
f.setAutoRequestFocus(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(b1);
}
public class Thr extends Thread
{
@Override
public void run()
{
int numsGenerated = 0;
double ave = 0;
synchronized(lock)
{
running=!running;
}
if (running == true)
{
while (true)
{
double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
numsGenerated++;
ave = ave + r;
System.out.println("Random: " + r);
synchronized(lock)
{
if (!running)
{
break;
}
}
}
synchronized(lock)
{
running = false;
}
}
System.out.println("");
System.out.println("All: " + ave);
System.out.println("Average: " + ave / numsGenerated);
running = true;
}
}
static Thr thread=null;
static void ActionListener()
{
b1.addActionListener(new ActionListener()//ActionListener
{
public void actionPerformed(ActionEvent e)//Execute when button is pressed
{
Average av=new Average();
if(thread==null)
{
thread=av.new Thr(); // should add in an executor
thread.start();
}
else
{
synchronized(lock)
{
running=false;
}
}
}
}); //ActionListenerEnd
}
public static void main(String[] args)//Main
{
JFrame();
ActionListener();
}
}
要有一个简单的线程,"Thread" 被继承并且 运行() 方法必须被覆盖才能使用它。 (你也可以使用 "Runnable" 而不是这个)
public class Thr extends Thread
{
@Override
public void run()
{
}
}
你开始喜欢
threadName.Start()
或
ExecutorObject.submit(threadName);
其中执行器对象有一个线程池,可以有效地 运行 并由执行器服务创建。
不要以
开始线程 threadname.run()
直接。
线程间通信也很重要。一个线程向某处留言,另一个线程读取。如果没有同步,它们可能会争夺变量的可见性,并可能发生错误的输出。
您可以锁定一个对象。
synchronized(lock)
{
}
所以这个块只能由单个线程进入,直到它退出这个块。你应该给其他线程留言,说 "its ready" 并用
唤醒它们(如果它们正在等待) synchronized(lock)
{
lock.notifyAll();
}
然后让消息离开线程(当前线程)进入等待状态,以便其他线程可以唤醒它并让它退出块。
synchronized(lock)
{
lock.notifyAll();
lock.wait();
}
但这还不够,因为当前线程不小心退出了等待状态,所以你可以强制它继续等待:
synchronized(lock)
{
lock.notifyAll();
while(condition)
lock.wait();
}
如果您确保一次只有一个线程可以访问一个变量,您可以使用它与其他线程通信。
您可以使用其他一些方法来设置障碍以同步某个点上的所有线程,这样在所有线程都遇到相同的障碍之前,任何线程都无法继续。更多的沟通会降低整体性能。
主程序也是线程,可以等待,通知,同步。