Mostrando a hora em tempo real

Boa tarde, estou desenvolvendo um pequeno projeto em que preciso mostrar a hora atual do computador em tempo real, até agora o que eu tenho é isso:

Date data = new Date();
DateFormat formato = new SimpleDateFormat("HH:mm:ss");
String formattedDate = formato.format(data);      
lblHoraAtual.setText(formattedDate);

Esse código me mostra a hora atual em que inicio o programa, porém gostaria que a hora fosse exibida de forma real como um relógio mesmo.

Vou passar uma ideia.
Use a classe Timer e a classe Date.
Como a classe Timer tem um temporizador, você consegue a cada 1s executar um conjunto de instruções.
Com a classe Date, você pega a hora do sistema e a imprime.
Só isso.
Ou você pode se dispor a criar um método que a partir de um momento inicial atualize horas, minutos e segundos, por meio da classe Timer também.
Ex. preferindo a classe Calendar:

    Timer timer;
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat hora = new SimpleDateFormat("hh:mm:ss");
    
    private void atualizaHoras(){
        timer = new Timer(1000, (ActionEvent e) ->{
        calendar.setTimeInMillis(calendar.getTimeInMillis()+1000);        
            System.out.println(hora.format(calendar.getTime()));
        });
        timer.start();
    }

Tenho esse código abaixo que eu utilizava para fazer este efeito de data/hora em tempo real, para isso é preciso a utilização de threads.

public class HorarioUtil extends Thread {  //classe utilizada para atualização da data/hora
  
    private JLabel hr;  
    private boolean mostrarData;  
  
    public HorarioUtil(JLabel hora) {  
        this.hr = hora;  
    }  
  
    public void mostrarData(boolean mostrar) {  
        if (mostrar) {  
            this.mostrarData = true;  
        } else {  
            this.mostrarData = false;  
        }  
    }  
  
    @Override  
    public void run() {  
        try {  
            while (true) {  
                Date d = new Date();  
                StringBuffer data = new StringBuffer();  
                if (mostrarData) {  
                    SimpleDateFormat sdfData = new SimpleDateFormat("dd/MM/yyyy");  
                    data.append(sdfData.format(d));  
                    data.append(" - ");  
                }  
                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");  
                this.hr.setText(data.toString() + sdf.format(d));  
                Thread.sleep(1000);  
                this.hr.revalidate();  
            }  
        } catch (InterruptedException ex) {  
            System.out.println("Problema na atualização da data/hora");  
            ex.printStackTrace();  
        }  
    }  
} 

public void mostrarHora() { // método de chamada para atualização da hora
        HorarioUtil horarioUtil = new HorarioUtil(meuJlabelHora);
        horarioUtil.mostrarData(true);
        Thread thHora = horarioUtil;
        thHora.start();
}

Uma approach diferente das já apresentadas:

import javax.swing.*;
import java.awt.*;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Main {

    private static final ScheduledExecutorService background = Executors.newSingleThreadScheduledExecutor();

    public static void main(String[] args) {

        // configuração da janela
        JFrame janela = new JFrame("Window");
        JLabel lblHora = new JLabel();
        janela.setLayout(new FlowLayout());
        janela.setBounds(0, 0, 200, 50);
        janela.add(lblHora);
        janela.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        janela.setVisible(true);
        // ---------------------

        long delayInicial = 0;
        long intervaloDeInvocacao = 1;
        TimeUnit segundos = TimeUnit.SECONDS;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss");
        Runnable tarefa = () -> SwingUtilities.invokeLater(
            () -> lblHora.setText(LocalTime.now().format(formatter))
        );
        background.scheduleAtFixedRate(tarefa, delayInicial, intervaloDeInvocacao, segundos);
    }
}
2 curtidas
 // Data e hora atual
    JLabel lblData = new JLabel();
    JLabel lblHora = new JLabel();
    lblData.setBounds(10,12,70,20);
    lblHora.setBounds(10,37,60,20);
    Thread th = new Thread(new Runnable() { //cria uma thread
        public void run() {
            while(true) { //roda indefinidamente
                Date data = Calendar.getInstance().getTime();
                DateFormat d = DateFormat.getDateInstance();
                DateFormat h = DateFormat.getTimeInstance();
                lblData.setText(d.format(data));
                lblHora.setText(h.format(data));     
                try {
                    Thread.sleep(1000); //espera 1 segundo para fazer a nova evolução
                } catch(InterruptedException ex){
                }
            }
        }
    }); th.start();

Valeu galera, vou testar as opções dadas.