Java 在';s使用了两个计数器和一个时钟,它们都在不同的线程中工作?

Java 在';s使用了两个计数器和一个时钟,它们都在不同的线程中工作?,java,multithreading,counter,clock,Java,Multithreading,Counter,Clock,我需要两个计数器像国际象棋时钟一样工作。第一个启动时,第二个停止。当第二个开始时,第一个停止。 与这两个计数器并行,我需要另一个永不停止的时钟 我正试着去做。我创建了两个计数器,工作正常,但当我创建一个新线程(总共3个线程)来运行时钟时,它会导致一些问题(同时增加两个计数器) 这些问题是否与同步问题有关?为什么它可以正确地运行2个线程而不能运行3个线程 //////////////////////////////// HOW THE OBJECTS ARE CREATED ///////////

我需要两个计数器像国际象棋时钟一样工作。第一个启动时,第二个停止。当第二个开始时,第一个停止。 与这两个计数器并行,我需要另一个永不停止的时钟

我正试着去做。我创建了两个计数器,工作正常,但当我创建一个新线程(总共3个线程)来运行时钟时,它会导致一些问题(同时增加两个计数器)

这些问题是否与同步问题有关?为什么它可以正确地运行2个线程而不能运行3个线程

//////////////////////////////// HOW THE OBJECTS ARE CREATED /////////////////////////

private Relogio relogioBranco, relogioPreto;
private RelogioGeral relogioGeral;

relogioBranco = new Relogio(relogioBrancoLabel);
relogioPreto = new Relogio(relogioPretoLabel);
relogioGeral= new RelogioGeral(relogioPretoLabel,menu);
new Thread(relogioBranco).start();
new Thread(relogioPreto).start();
new Thread(relogioGeral).start();

relogioBranco.rodarRelogio(false);
relogioPreto.rodarRelogio(false);
relogioGeral.rodarRelogio(true);

////////////////////////////////////// COUNTERS //////////////////////////////
// The clock will be used to autosave my game every 1 minute

package Janela;

import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JLabel;

public class Relogio implements Runnable, Serializable {

    private volatile AtomicInteger segundo, minuto, hora;
    private JLabel relogioLabel;
    private boolean relogioRodando;

    public Relogio(JLabel relogio) {
        segundo = new AtomicInteger();
        minuto =  new AtomicInteger();
        hora =  new AtomicInteger();

        minuto.set(0);
        hora.set(0);
        segundo.set(0);
        minuto.set(0);
        this.relogioLabel = relogio;
    }

    public void rodarRelogio(boolean rodar) {
        relogioRodando = rodar;

    }

    @Override
    public void run() {
        try {
            while (true) {
                Thread.sleep(1000);
                if (relogioRodando) {
                    segundo.incrementAndGet();
                    if (segundo.intValue() == 60) {
                        segundo.set(0);
                        minuto.incrementAndGet();
                        if (minuto.intValue() == 60) {
                            minuto.set(0);
                            hora.incrementAndGet();
                            if (hora.intValue() == 24) {
                                segundo.set(0);
                                minuto.set(0);
                                hora.set(0);
                            }
                        }
                    }
                    String tempo = String.format("%02d:%02d:%02d", hora.intValue(), minuto.intValue(), segundo.intValue());
                    relogioLabel.setText(tempo);
                }
            }
        } catch (InterruptedException ie) {
            System.out.println("EXCEÇÃO INTERRUPTED EXCEPTION");
        }
    }
}


///////////////////////////////////////////// CLOCK ///////////////////////////////////

package Janela;

import MesaTabuleiro.ArrayPecas;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class RelogioGeral implements Runnable, Serializable {

private volatile AtomicInteger segundo, minuto, hora;
private final JLabel relogioLabel;
private boolean relogioRodando;

public RelogioGeral(JLabel relogio, Menu menu) {
    segundo = new AtomicInteger();
    minuto = new AtomicInteger();
    hora = new AtomicInteger();

    segundo.set(0);
    minuto.set(0);
    hora.set(0);
    this.relogioLabel = relogio;
}

public void rodarRelogio(boolean rodar) {
    relogioRodando = rodar;
}

@Override
public void run() {
    try {
        while (true) {
            Thread.sleep(1000);
            if (relogioRodando) {
                segundo.incrementAndGet();
                if (segundo.intValue() == 60) {
                    segundo.set(0);
                    minuto.incrementAndGet();
                    if (minuto.intValue() == 60) {
                        minuto.set(0);
                        hora.incrementAndGet();
                        if (hora.intValue() == 24) {
                            segundo.set(0);
                            minuto.set(0);
                            hora.set(0);
                        }
                    }
                }
                String tempo = String.format("%02d:%02d:%02d", hora.intValue(), minuto.intValue(), segundo.intValue());
                relogioLabel.setText(tempo);
                if (minuto.intValue() %1 == 1) {
                    saveGame();
                }
            }
        }
    } catch (InterruptedException ie) {
        System.out.println("EXCEÇÃO INTERRUPTED EXCEPTION");
    }
}

public void saveGame() {
    JOptionPane.showMessageDialog(null, " 1 Minuto de Partida. Salvando Jogo.");
    FileOutputStream output;
    ObjectOutputStream oos = null;
    try {
        output = new FileOutputStream("jogo.ser");
        oos = new ObjectOutputStream(output);

        oos.writeObject(ArrayPecas.getInst().getPecasPretas());
        oos.writeObject(ArrayPecas.getInst().getPecasBrancas());
        oos.writeObject(ArrayPecas.getInst().getxPerdePr());
        oos.writeObject(ArrayPecas.getInst().getyPerdePr());
        oos.writeObject(ArrayPecas.getInst().getxPerdeBr());
        oos.writeObject(ArrayPecas.getInst().getyPerdeBr());

        oos.writeObject(TelaMenuJogo.getTela().getXequeVsbl());
        oos.writeObject(TelaMenuJogo.getTela().getXequeMateVsbl());
        oos.writeObject(TelaMenuJogo.getTela().getHistoricoTxt());
        oos.writeObject(TelaMenuJogo.getTela().getJaDesenhou());
        oos.writeObject(TelaMenuJogo.getTela().getLinha());
        oos.writeObject(TelaMenuJogo.getTela().getColuna());
        oos.writeObject(TelaMenuJogo.getTela().getLinPecaSel());
        oos.writeObject(TelaMenuJogo.getTela().getColPecaSel());
        oos.writeObject(TelaMenuJogo.getTela().getQtdJogadas());
        oos.writeObject(TelaMenuJogo.getTela().getJogador());

    } catch (FileNotFoundException ex) {
        JOptionPane.showMessageDialog(null, "Arquivo nao encontrado");
    } catch (IOException ex) {
        ex.printStackTrace();
        JOptionPane.showMessageDialog(null, "Erro ao tentar gravar no arquivo de saida");
    } finally {
        if (oos != null) {
            try {
                oos.close();
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Erro ao fechar arquivo de saida");
            }
        }
    }
}

}

我认为您将相同的标签传递给主时钟,就像传递给其他时钟一样:

relogioBranco = new Relogio(relogioBrancoLabel);
relogioPreto = new Relogio(relogioPretoLabel);
relogioGeral= new RelogioGeral(relogioPretoLabel,menu);
它不应该有自己的标签吗


我认为这个问题与并发无关。只有当两个线程在处理一个资源时(例如,线程a和线程b都在读取同一个字段),才会出现并发问题。这里的情况并非如此。每个线程都处理自己的变量/对象。

我认为两个计数器不需要两个线程。相反,您可以有一个线程交替迭代计数器。