簡體   English   中英

多線程計時器無法正常工作

[英]Multithread timer not working correctly

再次,請幫助我! 在下面的代碼中,我想通過按一下按鈕來推動計時器線程並在Label中鍵入它來開始。 每次按該按鈕應啟動一個新線程,並在每個標簽上標記它。 但不幸的是,每個標簽都寫入了相同的計時器。 您能幫我們做對嗎? 如果您能告訴我錯誤,那是什么意思?

public class TimerThreads implements ActionListener{

    JFrame jFrame = new JFrame();
    JLabel[] labels;
    int second = 0;
    int minute = 0;
    String s = "";
    String m = "";
    int l = 0;


    public TimerThreads(){
        JLabel one = new JLabel();
        JLabel two = new JLabel();
        JLabel three = new JLabel();
        JLabel four = new JLabel();
        labels = new JLabel[]{one, two, three, four};

        jFrame.setLayout(new GridLayout(0, 2, 5, 5));
        jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JButton start = new JButton("Start");
        start.addActionListener(this);

        JButton stop = new JButton("Stop");
        stop.addActionListener(this);

        jFrame.add(start);
        jFrame.add(stop);
        jFrame.setVisible(true);
        jFrame.pack();
    }

    public static void main(String[] args) {
        new TimerThreads();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String select = e.getActionCommand();
        switch(select){
            case "Start":
                jFrame.add(labels[l]);
                jFrame.revalidate();
                jFrame.repaint();
                TimerThread t = new TimerThread(labels[l]);
                t.start();
                l++;
                break;
            case "Stop":
                //
                break;
        }
    }

    class TimerThread extends Thread{
        JLabel jLabel;

        public TimerThread(JLabel jLabel) {
            this.jLabel = jLabel;
        }

        @Override
        public void run() {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    second++;
                    if(String.valueOf(second).length() == 1){
                        s = "0";
                    }
                    else{
                        s = "";
                    }
                    if(second == 60){
                        second = 0;
                        s = "0";
                        minute++;
                    }

                    if(String.valueOf(minute).length() == 1){
                        m = "0";
                    }
                    jLabel.setText(m + String.valueOf(minute) + ":" + s + String.valueOf(second));
                }
            },0, 1000);
        }
    }
}

您的錯誤的原因在這里:

public class TimerThreads implements ActionListener {

    JFrame jFrame = new JFrame();
    JLabel[] labels;

    // ***** these fields below
    int second = 0;     
    int minute = 0;
    String s = "";
    String m = "";
    // ***** these fields above

    int l = 0;

這四個字段是該類的實例字段,並且由您創建的每個TimerTask實例共享,因此所有字段將顯示相同的准確時間。

解決方案是使這些字段位於嵌套類的本地:

public class TimerThreads implements ActionListener {

    JFrame jFrame = new JFrame();
    JLabel[] labels;
    // int second = 0;
    // int minute = 0;
    // String s = "";
    // String m = "";
    int l = 0;

    public TimerThreads() {
        //.....
    }

    // ....


    class TimerThread extends Thread {
        JLabel jLabel;

        public TimerThread(JLabel jLabel) {
            this.jLabel = jLabel;
        }

        @Override
        public void run() {
            java.util.Timer timer = new java.util.Timer();
            timer.scheduleAtFixedRate(new TimerTask() {

                // ***** add these fields here
                int second = 0;
                int minute = 0;
                String s = "";
                String m = "";

話雖如此,由於使用了錯誤的Timer(即java.util.Timer)(應使用Swing Timer或javax.swing.Timer),因此代碼風險很大。 這一點非常重要,因為后一個Timer與Swing事件模型可以很好地配合並防止線程沖突。 請查看Swing計時器教程

其他問題:使用固定大小的數組,如果用戶希望運行4個以上的線程,則可能會出現索引超出范圍的風險。 請改用ArrayList。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM