Skip to content

6 Multihilo

Introducción

Crear una aplicación Swing que soporte múltiples hilos (multithreading) implica manejar correctamente las actualizaciones de la interfaz de usuario para evitar problemas de concurrencia y asegurar una experiencia de usuario fluida. Swing no es seguro para el uso de hilos, lo que significa que todas las actualizaciones de la interfaz de usuario deben realizarse en el Event Dispatch Thread (EDT).

EL EDT es el hilo donde se deben ejecutar todas las actualizaciones de la interfaz de usuario. Manipular componentes de Swing desde cualquier otro hilo puede causar problemas impredecibles.

El SwingWorker es una clase conveniente para realizar tareas en segundo plano sin bloquear el EDT. Permite ejecutar tareas en un hilo separado y actualizar la interfaz de usuario de forma segura.

SwingUtilities.invokeLater() es un método útil para ejecutar código en el EDT.

Proyecto Multithreading

public class MultithreadingExample {

    private JFrame frame;
    private JButton startButton;
    private JLabel statusLabel;
    private JProgressBar progressBar;

    public MultithreadingExample() {
        // Crear el marco
        frame = new JFrame("Multithreading in Swing");
        frame.setSize(400, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setLayout(new FlowLayout());

        // Crear componentes
        startButton = new JButton("Start Task");
        statusLabel = new JLabel("Status: Waiting");
        progressBar = new JProgressBar(0, 100);

        // Agregar acción al botón
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startBackgroundTask();
            }
        });

        // Agregar componentes al marco
        frame.add(startButton);
        frame.add(statusLabel);
        frame.add(progressBar);
    }

    private void startBackgroundTask() {
        SwingWorker<Void, Integer> worker = new SwingWorker<>() {
            @Override
            protected Void doInBackground() throws Exception {
                for (int i = 0; i <= 100; i++) {
                    Thread.sleep(50); // Simula una tarea pesada
                    publish(i); // Envía el progreso
                }
                return null;
            }

            @Override
            protected void process(java.util.List<Integer> chunks) {
                int progress = chunks.get(chunks.size() - 1);
                progressBar.setValue(progress);
                statusLabel.setText("Status: " + progress + "% completed");
            }

            @Override
            protected void done() {
                statusLabel.setText("Status: Task Completed!");
                startButton.setEnabled(true);
            }
        };

        startButton.setEnabled(false);
        worker.execute();
    }

    public void show() {
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            MultithreadingExample example = new MultithreadingExample();
            example.show();
        });
    }

}