我想创建一个Java程序,允许我重复 - 5,4,3,2,1,0 FIRE - 我想要的次数。 我开始搜索如何创建倒计时,我使用计时器计划,所以我可以每1秒设置一次JTextFields文本(产生正常倒计时的效果)。但问题是,当我想重复时,免得说,这次倒计时的2倍,我的java代码同时开始倒计时,而不是等待第一个完成倒计时。我的主要目标是单击按钮并开始一定数量的倒计时。要生成的倒计时数在启用的JTextField中输入。
我将整个代码留在这里:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import javax.swing.*;
public class Counter {
public static class MyThread implements Runnable {
private JTextField tx1;
private JTextField tx2;
CountDownLatch latch;
int count;
public MyThread (JTextField tx1,JTextField tx2,CountDownLatch latch) {
this.tx1=tx1;
this.tx2=tx2;
this.latch = latch;
}
public void run() {
tx1.setText("");
tx2.setText("");
count=5;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
int counter=0;
public void run() {
tx1.setText("");
tx1.setText(Integer.toString(count));
System.out.println("!");
count--;
counter++;
if (counter==6){
tx2.setText("FIRE");
this.cancel();
}
}
}, 1000,1000);
latch.countDown();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame ("Counter");
JPanel panel=new JPanel ();
panel.setLayout(new GridLayout(3,2));
JButton bt1=new JButton("Start");
JButton bt2=new JButton("Reset");
JLabel lb1=new JLabel ("Puffs");
final JTextField tx1= new JTextField(5);
final JTextField tx2= new JTextField(10);
final JTextField tx3= new JTextField(5);
tx1.setEnabled(false);
tx2.setEnabled(false);
panel.add(tx1);
panel.add(tx2);
panel.add(lb1);
panel.add(tx3);
panel.add(bt1);
panel.add(bt2);
frame.add(panel);
CountDownLatch latch = new CountDownLatch(2);
new Thread(new MyThread(tx1, tx2,latch)).start();
new Thread(new MyThread(tx1, tx2,latch)).start();
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bt1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
// int tr=Integer.parseInt(tx3.getText());
}
});
bt2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
}
});
////
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
Rectangle bounds = gc.getBounds();
Dimension size = frame.getPreferredSize();
frame.setLocation((int) ((bounds.width / 2) - (size.getWidth() / 2)),
(int) ((bounds.height / 2) - (size.getHeight() / 2)));
frame.setVisible(true);
frame.pack();
}
}
抱歉格式错误和写错。 非常感谢你的帮助!
已编辑的代码
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import javax.swing.*;
public class Counter {
public static class MyThread implements Runnable {
private JTextField tx1;
private JTextField tx2;
int count;
public MyThread (JTextField tx1,JTextField tx2) {
this.tx1=tx1;
this.tx2=tx2;
}
public void run() {
tx1.setText("");
tx2.setText("");
count=5;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
int counter=0;
public void run() {
tx1.setText("");
tx1.setText(Integer.toString(count));
System.out.println("!");
count--;
counter++;
if (counter==6){
tx2.setText("FIRE");
this.cancel();
}
}
}, 1000,1000);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame ("Counter");
JPanel panel=new JPanel ();
panel.setLayout(new GridLayout(3,2));
JButton bt1=new JButton("Start");
JButton bt2=new JButton("Reset");
JLabel lb1=new JLabel ("Puffs");
final JTextField tx1= new JTextField(5);
final JTextField tx2= new JTextField(10);
final JTextField tx3= new JTextField(5);
tx1.setEnabled(false);
tx2.setEnabled(false);
panel.add(tx1);
panel.add(tx2);
panel.add(lb1);
panel.add(tx3);
panel.add(bt1);
panel.add(bt2);
frame.add(panel);
bt1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
// int tr=Integer.parseInt(tx3.getText());
Thread t1 = new Thread(new MyThread(tx1, tx2));
Thread t2 = new Thread(new MyThread(tx1, tx2));
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
bt2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
}
});
////
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
Rectangle bounds = gc.getBounds();
Dimension size = frame.getPreferredSize();
frame.setLocation((int) ((bounds.width / 2) - (size.getWidth() / 2)),
(int) ((bounds.height / 2) - (size.getHeight() / 2)));
frame.setVisible(true);
frame.pack();
}
}
答案 0 :(得分:0)
是的,这将同时启动Timer
。使用此代码。
CountDownLatch latch = new CountDownLatch(2);
new Thread(new MyThread(tx1, tx2,latch)).start();
new Thread(new MyThread(tx1, tx2,latch)).start();
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但是你可以让第二个计时器在第一个计时器结束后执行。 在第一个计时器结束后把它放好。
new Thread(new MyThread(tx1, tx2,latch)).start();
答案 1 :(得分:0)
如果你在不同的线程中启动计时器,它们自然会被同时执行:这就是线程的目的。
如果要同步它们,例如,在前一个线程完成时启动一个线程,则可以使用join()
函数,该函数将“暂停”代码直到线程完成。
Thread t1 = new Thread(new MyThread(tx1, tx2, latch));
Thread t2 = new Thread(new MyThread(tx1, tx2, latch));
t1.start();
t1.join();
t2.start();
t2.join();
// ...
因此,t2仅在t1结束后才开始 你可以将它应用于for循环,在循环中你跟踪前一个线程,并在oldThread.join()之后开始下一个。
希望它可以帮到你!
答案 2 :(得分:0)
嘿,我终于找到了代码中的缺陷。您发布的第一个代码(不是已编辑的代码)是正确的代码,也是使用CountDownLatch
(用于同步)的正确方法。
我刚刚更改了您的MyThread
班级run()
方法。只是看看它。
public static class MyThread implements Runnable {
private JTextField tx1;
private JTextField tx2;
CountDownLatch latch;
int count;
public MyThread (JTextField tx1,JTextField tx2,CountDownLatch latch) {
this.tx1=tx1;
this.tx2=tx2;
this.latch = latch;
}
public void run() {
tx1.setText("");
tx2.setText("");
count=5;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
int counter=0;
public void run() {
tx1.setText("");
tx1.setText(Integer.toString(count));
System.out.println("!");
count--;
counter++;
if (counter==6){
tx2.setText("FIRE");
latch.countDown();
this.cancel();
}
}
}, 1000,1000);
//latch.countDown();Detailed Explaination is below.
}
}
latch.countDown()
在第一次Thread
开始时直接执行。因此,您希望将其置于if
条件中。因此第二个Thread
将等待第一个Thread
latch.countDown()
即将完成。
CountDownLatch
方法就像一个网关开启者。当调用此函数时,Thread
中的倒计时将递减1.因此CountDownLatch
中的下一个{{1}}将会被执行。
希望这会对你有所帮助。