Barra de progresso, Thread e emissão de relatórios

Pessoal, no meu projeto eu criei uma tela que é responsável por definir (o usuário escolhe) o tipo de relatório a ser gerado e, ao clicar no botão “Gerar”, de acordo com a escolha do usuário (JComboBox), há um switch que define o caso. Até aí tudo bem, funciona perfeitamente. No entanto, eu percebi que há certo “atraso” entre acionar o botão Gerar e o carregamento do PDF com o relatório. Então para situar o usuário (se o relatório está sendo gerado ou não), eu resolvi colocar uma barra de progresso na tela, de forma que as coisas estão da seguinte forma:

public class TelaRelatorioCadastral extends javax.swing.JFrame {
    private final int OPCAO_INVALIDA = 0;
    private final Map parametros = new HashMap();
    private volatile boolean terminado = true;
    private Thread thredRelatorio;
    private Thread threadBarraProgresso;
    /**
     * Creates new form TelaRelatorioCadastral
     */
    public TelaRelatorioCadastral() {
        UIManager.put("nimbusOrange", new Color(0, 102, 0));
        initComponents();
        setIcone();
        configurarComponente();
    }
	/**[...]*/

	private void btnGerarActionPerformed(java.awt.event.ActionEvent evt) {                                         
        if(cbxItemRelatorio.getSelectedIndex() != OPCAO_INVALIDA){
            int opcao =  cbxItemRelatorio.getSelectedIndex();
            InputStream stream;
            ResultSet resultSet;
            Connection conexao;
            ControlaThread controle;
            parametros.put("logo", "/img/");
            parametros.put("SUBREPORT_DIR", "/relatorio/");
            terminado = false;
            
            try{
                switch(opcao){
                    case 1:
                        stream = getClass().getResourceAsStream(
                                "/relatorio/rc_plano_conta.jasper");
                        resultSet = dao.ContaContabil.retornarPlanoContas();
                        conexao = null;
                        
                        construirRelatorio(stream, resultSet, conexao, this);
                        break;
                    case 5:
                        stream = getClass().getResourceAsStream(
                                "/relatorio/rc_cliente.jasper");
                        resultSet = null;
                        conexao = ConectaBancoDeDados.getConexao();
                        
                        construirRelatorio(stream, resultSet, conexao, this);
                        break;
                    case 9:
                        stream = getClass().getResourceAsStream(
                                "/relatorio/rc_raca.jasper");
                        resultSet = dao.Raca.retornarRelatorioRaca();
                        conexao = null;
                        
                        construirRelatorio(stream, resultSet, conexao, this);
                        
                        break;
                }
            }catch(SQLException sqle){
                System.out.println("ERRO: " + sqle.getMessage());
                JOptionPane.showMessageDialog(this, "Relatório não foi gerado. " 
                    + sqle.getMessage());
            }
        }else{
             JOptionPane.showMessageDialog(this, "Opção inválida!");
        }
    }
	
	private void construirRelatorio(InputStream caminho, ResultSet resultados, 
            Connection conexao, TelaRelatorioCadastral telaCad) 
            throws SQLException{
        final int CEM_MILISSEGUNDOS = 100;
        final int DEZ_MILISSEGUNDOS = 10;
        
        thredRelatorio = new Thread(new Runnable(){
            @Override
            public void run(){ 
                if(resultados != null)
                    GeradorDeRelatorio.gerarRelatorio(caminho, parametros,
                        resultados, telaCad);
                if(conexao != null)
                    GeradorDeRelatorio.gerarRelatorio(caminho, parametros,
                        conexao);
                thredRelatorio = null;
            }
        });
        
        threadBarraProgresso = new Thread(new Runnable(){
            @Override
            public void run(){
                while(barraProgresso.getValue() < 100){
                    try{
                        Thread.sleep(CEM_MILISSEGUNDOS);
                        barraProgresso.setValue(barraProgresso.getValue() 
                                + DEZ_MILISSEGUNDOS);
                        
                        descreverProgresso(barraProgresso.getValue());
                        
                        if(barraProgresso.getValue() == 100)
                            threadBarraProgresso.interrupt();
                        
                    }catch(InterruptedException iex){
                        System.out.println("ERRO: " + iex.getMessage());
                        break;
                    }
                }
            }
        });
        
        threadBarraProgresso.start();
        thredRelatorio.start();
    }
    
    private void descreverProgresso(int progresso){
        if(progresso < 25)
            lblStatus.setText("Reunindo dados...");
        if(progresso > 25 && progresso < 50)
            lblStatus.setText("Obtendo parâmetros...");
        if(progresso > 50 && progresso < 100)
            lblStatus.setText("Construindo o relatório...");
        if(progresso == 100)
            lblStatus.setText("Concluído!");
    }
	
	/*[...]*/
}

O fato é que eu não consigo parar a Thread (deixar em state TERMINATED), pois elas ficam sempre no estado RUNNABLE (ao aplicar o método getState() na thread, aparece esse estado). Tanto é que se eu fechar a tela de emissão de relatórios e abrir novamente (a tela é aberta por meio de outra que contém menus de opções MenuBar), o combobox vem preenchido com a última opção escolhida e a barra de progresso em 100%. Eu confesso que é a primeira vez que estou trabalhando com threads e talvez não esteja codificando corretamente. Contudo, já tente utilizar flags para ‘encerrar’ as threds, mas aparentemente não resolve. O que será que estou fazendo de errado? Como trabalhar corretamente com Threads, Há outra forma de fazer a mesma coisa sem manipular threads diretamente?

Desde de já agradeço.