Threads in Java

Asked

Viewed 101 times

-2

This is the first time I’ve been working with Threads. I created two threads, one to run the report generator (iReport) and one to operate a progress bar (Jprogressbar). However, even using flag, Thread is not terminated (state - TERMINATED), that is, it remains in the RUNNABLE state. See:

package util;

import java.io.InputStream;
import java.sql.ResultSet;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JProgressBar;
import visao.TelaRelatorioCadastral;

/**
 *
 * @author JFSJUNIOR
 */
public class ControlaThread{
    private Thread threadBarraProgresso;
    private Thread threadEmissaoRelatorio;
    private final AtomicBoolean rodando = new AtomicBoolean(false);
    private JProgressBar progresso;
    private InputStream fluxo;
    private ResultSet dados;
    private TelaRelatorioCadastral tela;
    private Map param;

    public ControlaThread(JProgressBar barraProgresso, 
            InputStream caminho, ResultSet resultados, 
            TelaRelatorioCadastral telaCad, Map paramentros){
        progresso = barraProgresso;
        fluxo = caminho;
        dados = resultados;
        tela = telaCad;
        param = paramentros;
    }

    public void start(){
        threadBarraProgresso = new Thread(new Runnable(){
            @Override
            public void run() {
                rodando.set(true);
                while(progresso.getValue() < 100 && rodando.get()){
                    try {
                        Thread.sleep(100);
                        progresso.setValue(progresso.getValue() + 10);
                    } catch (InterruptedException iex) {
                        System.out.println("ERRO: " + iex.getMessage());
                    }
                }
            }
        });

        threadEmissaoRelatorio= new Thread(new Runnable(){
            @Override
            public void run() {
                if(rodando.get())
                    GeradorDeRelatorio.gerarRelatorio(fluxo, param, dados, tela);
            }
        });

        threadBarraProgresso.start();
        threadEmissaoRelatorio.start();
    }

    public void stop(){
        rodando.set(false);
        System.out.println("Finalizado");
    }
}

Everything works, but the screen that calls this class always comes set with the last option chosen (in a Jcombobox) and the previous bar is completed (100%). How to stop Threads without using the deprecated stop() because the flags are not working? Where am I missing?

Additional information

1 - Checking the name of threads in the stop method:

public void stop(){
        rodando.set(false);
        System.out.println("Finalizado");
        System.out.println("NomeThreadBE: " + threadBarraProgresso.getName());
        System.out.println("NomeThreadER: " + threadEmissaoRelatorio.getName());
}

generates:

run:
Finalizado
NomeThreadBE: Thread-2
NomeThreadER: Thread-3

Here the button method:

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;


                        controle = new ControlaThread(barraProgresso, stream, resultSet, this, parametros);
                        controle.start();
                        controle.stop();
                        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!");
        }
    }

Note: As I only built the race report, I am using case 9 for the tests.

===========================================================================

Updated code

Case 9 of the button:

case 9:
    stream = getClass().getResourceAsStream(
            "/relatorio/rc_raca.jasper");
    resultSet = dao.Raca.retornarRelatorioRaca();
    conexao = null;
    construirRelatorio(stream, resultSet, conexao, this);
    break;

and the previous class code I transferred to the build method with some modifications:

private void construirRelatorio(InputStream caminho, ResultSet resultados, 
            Connection conexao, TelaRelatorioCadastral telaCad) 
            throws SQLException{
        final int SONECA = 500;
        final int PERIODO = 10;

        thredRelatorio = new Thread(new Runnable(){
            @Override
            public void run(){
                rodando.set(true);
                if(rodando.get()){
                    if(resultados != null){
                        GeradorDeRelatorio.gerarRelatorio(caminho, parametros,
                            resultados);
                    }
                    if(conexao != null)
                        GeradorDeRelatorio.gerarRelatorio(caminho, parametros,
                            conexao);
                }
                stop();
            }
        });

        threadBarraProgresso = new Thread(new Runnable(){
            @Override
            public void run(){
                rodando.set(true);
                while(barraProgresso.getValue() < 100 && rodando.get()){
                    try{
                        Thread.sleep(SONECA);
                        barraProgresso.setValue(barraProgresso.getValue() 
                                + PERIODO);

                        descreverProgresso(barraProgresso.getValue());

                    }catch(InterruptedException iex){
                        System.out.println("ERRO: " + iex.getMessage());
                        break;
                    }
                }
                thredRelatorio.start();
                telaCadastro.dispose();
                reconfigurarCampos();
            }
        });
        threadBarraProgresso.start();
    }

The Stop method:

private void stop(){
        rodando.set(false);

        System.out.println("Finalizado");
        System.out.println("NomeThreadBE: " + threadBarraProgresso.getName());
        System.out.println("NomeThreadER: " + thredRelatorio.getName());

        System.out.println("StatusBE: " + threadBarraProgresso.getState());
        System.out.println("StatusER: " + thredRelatorio.getState());
    }

And the method that describes progress:

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!");
    }

I put the report thread start() method at the end (after while) of the progress bar thread to ensure that the report thread will only be called when the progress bar thread has TERMINATED status. I tried this using John, but it is difficult to hit the threads' 'time' (hence I would have to put the value of NAP very low), since in certain situations the report is generated with the progress bar at 20%, 30%, hence the bar thread enters WAITING or TIMED-WAITING. I ran the test generating the report without calling the method JasperViewer.viewReport(jasperPrint, false); to see if this is what kept the thread in RUNNABLE, but to no avail.

Thanks in advance.

  • in the current context there you have at least 3 threads running, the main and two more, how do you know that the one that is runnable is the one that should have finished? another detail, your thread.Leep there is 100 milliseconds, if your bar is worth 100, in a second it already completes from the moment you give start

  • Yes, the main thread and the two I created. I do: threadBarraProgresso.getState(), threadEmissaoRelatorio.getState(), for example. Also I confirm threadBarraProgressio.getName(), threadEmissaoRelatorio.getName() or getID() to know.

  • but where is this in your example? where is the stop call?

  • I put more details.

1 answer

0

In my view it’s not that she’s finishing, it’s that you’re not having time to see her finish, even if you seven running it to false, it’s not automatic, the thread is already there inside the while running, will do the whole process and at the same time comes your print indicating that it is running, if you really want to see that the state has ended, after setting the flag you can give one . Join() in the bar thread you will see that in fact it will end,

public void stop(){
        rodando.set(false);
        threadBarraProgresso.join();
        System.out.println("Finalizado");
        System.out.println("NomeThreadBE: " + threadBarraProgresso.getState());
}

the fact that the bar already appears complete was as I explained, with a thread of 100 milliseconds and a bar of percentage 100 in 1 second it already complete, try to change it (increase the thread size.Leep for example) that you will see it going up,

while(progresso.getValue() < 100 && rodando.get()){
                    try {
                        Thread.sleep(1000);
                        progresso.setValue(progresso.getValue() + 10);
                    } catch (InterruptedException iex) {
                        System.out.println("ERRO: " + iex.getMessage());
                    }
                }

the problem of the already selected combobox ta appear not in your code, it is something else totally out of that you posted ai

  • On the bar, it presses at the right time. I made it close (Dispose) when finished loading. But if I opened the screen again it comes with the data (loaded bar) and Jcombbox set with the last option selected. I made some modifications and the bar thread is now giving TERMINATED, but the report thread gets RUNNABLE.I ran a test by calling just a String.out.print instead of the class that generates the report, but it keeps coming as RUNNABLE. I’ll use Join to see if you can solve this case.

  • I made some changes to the code (edited my question). Now the progress bar thread ends, but the report thread keeps running.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.