Finalizar uma Thread a partir de uma outra Thread

Olá pessoal, a duvida é a seguinte:
Ao clicar em um botão, em um Frame Principal, crio uma Thread para uma Classe X, que implementa Runnable.

Essa Classe X, dentro do método run realiza as seguintes tarefas:
[list]Cria uma nova Thread para uma Classe Y, que é um Frame e que também implementa Runnable, e[/list]
[list]Realiza certos cálculos.[/list]

Queria que, ao término do cálculo, a Thread da Classe X finalizasse a Thread da Classe Y.

Frame Principal

public class FramePrincipal extends javax.swing.JFrame {

    public FramePrincipal() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jButtonExecutar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Principal");
        setResizable(false);

        jButtonExecutar.setText("Executar");
        jButtonExecutar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonExecutarActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(100, 100, 100)
                .addComponent(jButtonExecutar)
                .addContainerGap(111, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(71, 71, 71)
                .addComponent(jButtonExecutar)
                .addContainerGap(80, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>

    private void jButtonExecutarActionPerformed(java.awt.event.ActionEvent evt) {
        Algoritmo proc = new Algoritmo();
        Thread th = new Thread(proc);
        th.start();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new FramePrincipal().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JButton jButtonExecutar;
    // End of variables declaration
}

Classe X

public class Algoritmo implements Runnable{
    
    @Override
    public void run(){
        geraProcesso();
        algoritmoG();
        // Finalizar a Thread th.
    }  
    
    public void geraProcesso(){
        FrameProgresso prog = new FrameProgresso();
        prog.setVisible(true);
        Thread th = new Thread(prog);
        th.start();
    }
    
    public void algoritmoG(){
        JOptionPane.showMessageDialog(null, "Inicio do Alg");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException ex) {
            Logger.getLogger(Algoritmo.class.getName()).log(Level.SEVERE, null, ex);
        }
        JOptionPane.showMessageDialog(null, "Fim do Alg");
    }
}

Classe Y

public class FrameProgresso extends javax.swing.JFrame implements Runnable {

    /**
     * Creates new form FrameProgresso
     */
    public FrameProgresso() {
        initComponents();
    }

    @Override
    public void run() {
        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imagens/carregando.gif"))); // NOI18N
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setResizable(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>
    // Variables declaration - do not modify
    private javax.swing.JLabel jLabel1;
    // End of variables declaration
}

Alguém poderia me dizer como parar o método run da Classe Y quando a Thread da Classe X terminar de fazer os cálculos?
Desde já agradeço!
Ate++

Você sabe que as threads podem notificar umas as outras, certo?
Quando aquela que está realizando os cálculos encerrar seu processamento, poderá avisar as interessadas e, então, você pode ir encerrando o processamento sequencialmente.

[quote]Você sabe que as threads podem notificar umas as outras, certo?
Quando aquela que está realizando os cálculos encerrar seu processamento, poderá avisar as interessadas e, então, você pode ir encerrando o processamento sequencialmente.
[/quote]

Vou dar uma pesquisada sobre comunicação de Thread, se consegui volto e posto a solução.
Obrigado pela dica, caso eu não consiga, poderia me ajudar?