Matar Thread com Thread.stop()

11 respostas
L

Olá pessoal.

Nas ultimas versões do Java deixarão o Thread.stop() obsoleto. e porque?

Para começar, este método ainda funciona. Mas não usem ele ou “sofrerá as conseqüências”.

Quando se está executando um programa Java se cria muitos objetos. No Método run da sua Thread também se pode criar muitos objetos. Bem! Se caso eu chamar o Thread.stop() bem na hora da criação de objeto. Sabem o que acontece? O objeto é criado “pela metade”(“criado pela metade” foi apenas uma expressão), então o seu programa todo morre e você verá, muito provavelmente, uma mensagem parecida com esta.

#

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006dc3f5d6, pid=548, tid=3412

JRE version: 6.0_20-b02

Java VM: Java HotSpot™ 64-Bit Server VM (16.3-b01 mixed mode windows-amd64 )

Problematic frame:

V [jvm.dll+0x3af5d6]

An error report file with more information is saved as:

C:\Users\leonardo\Documents\NetBeansProjects\Testes\hs_err_pid548.log

If you would like to submit a bug report, please visit:

http://java.sun.com/webapps/bugreport/crash.jsp

#

Por isso se você quiser matar um Thread no Java. Implemente a sua solução, mas tenha cuidado!

11 Respostas

E

O correto é usar uma classe que implemente a interface java.concurrent.Callable em vez de uma Thread.

Usando a interface Future (um objeto de uma classe que implementa Future é retornada pelo método submit de ExecutorService), é possível cancelar e checar se esse Callable foi cancelado.

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

Um exemplo do uso de Future e Callable está no Javadoc acima.

L

O correto é usar uma classe que implemente a interface java.concurrent.Callable em vez de uma Thread.

Usando a interface Future (um objeto de uma classe que implementa Future é retornada pelo método submit de ExecutorService), é possível cancelar e checar se esse Callable foi cancelado.

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

Um exemplo do uso de Future e Callable está no Javadoc acima.

Muito interessante. Não fui apresentado a esta classe. Não costumo mexer com Thread já que meu forte é trabalhar com web.

Mas isso garante que a execução irá para no tempo certo?

V

O método stop() foi deprecated pois ele gera leak de recursos:

  1. Locks de sincronização ficam presos;
  2. Arquivos podem ficar abertos;
  3. Conexões de BD também.

Em resumo, você joga isso numa thread e ela aborta na hora. Nada garante que o que foi reservado por ela seja liberado.

A
2. Arquivos podem ficar abertos;

vivi isso um tempo desses por aqui!

e como ficaria a implementação por exemplo:

Thread thread = new Thread(minhaClasse, id);
thread.start();

//Depois de um Tempo
thread.stop();

abraço!

E

leo_mf:

Mas isso garante que a execução irá para no tempo certo?

Não: o método “cancel” apenas força uma exceção InterruptedException na thread que está executando esse Callable. Se a thread estiver porventura em um ponto em que ela não consegue ser interrompida (tipicamente quando está travada em um loop fazendo contas, sem fazer I/O como arquivos ou sockets) então ela só irá ser interrompida quando sair desse loop.

E
aeciovc:
2. Arquivos podem ficar abertos;

vivi isso um tempo desses por aqui!

e como ficaria a implementação por exemplo:

Thread thread = new Thread(minhaClasse, id);
thread.start();

//Depois de um Tempo
thread.stop();

abraço!

Veja o exemplo em http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

V

O certo seria chamar Interrupt(), que faz o que o cancel() que o entanglement está citando faz. Com as mesmas limitações.
E procurar APIs que tenham timeouts máximos para operações críticas (como I/O ou leituras de sockets).

E

Exemplo.

package guj;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

class Atualizador implements Callable<Void> {
    public Atualizador(JProgressBar prb) {
        this.prb = prb;
    }

    @Override
    public Void call() throws Exception {
        while (true) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    prb.setValue(val++);
                }
            });
            if (val >= 100)
                val = 0;
            Thread.sleep(100);
        }
    }

    private JProgressBar prb;
    private int val = 0;
}

public class ExemploCallable extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel jContentPane = null;
    private JPanel pnlBotoes = null;
    private JButton btnIniciar = null;
    private JButton btnParar = null;
    private JProgressBar prbProgresso = null;

    private ExecutorService executor;
    private FutureTask<Void> future;

    private JPanel getPnlBotoes() {
        if (pnlBotoes == null) {
            pnlBotoes = new JPanel();
            pnlBotoes.setLayout(new FlowLayout());
            pnlBotoes.add(getBtnIniciar(), null);
            pnlBotoes.add(getBtnParar(), null);
        }
        return pnlBotoes;
    }

    private JButton getBtnIniciar() {
        if (btnIniciar == null) {
            btnIniciar = new JButton();
            btnIniciar.setText("Iniciar!");
            btnIniciar.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    btnIniciar.setEnabled(false);
                    future = new FutureTask<Void>(new Atualizador(prbProgresso));
                    executor.execute(future);
                    btnParar.setEnabled(true);
                }
            });
        }
        return btnIniciar;
    }

    private JButton getBtnParar() {
        if (btnParar == null) {
            btnParar = new JButton();
            btnParar.setText("Parar!");
            btnParar.setEnabled(false);
            btnParar.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    btnParar.setEnabled(false);
                    future.cancel(true);
                    btnIniciar.setEnabled(true);
                }
            });
        }
        return btnParar;
    }

    private JProgressBar getPrbProgresso() {
        if (prbProgresso == null) {
            prbProgresso = new JProgressBar();
            prbProgresso.setStringPainted(true);
        }
        return prbProgresso;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ExemploCallable thisClass = new ExemploCallable();
                thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                thisClass.setVisible(true);
            }
        });
    }

    public ExemploCallable() {
        super();
        initialize();
        executor = Executors.newCachedThreadPool();
    }

    private void initialize() {
        this.setSize(300, 111);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setContentPane(getJContentPane());
        this.setTitle("Exemplo Callable");
    }

    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(new BorderLayout());
            jContentPane.add(getPnlBotoes(), BorderLayout.SOUTH);
            jContentPane.add(getPrbProgresso(), BorderLayout.CENTER);
        }
        return jContentPane;
    }
}


L

Bom pessoal para quem gosta de mexer com Thread, tenho uma boa prática para vocês.

ScheduledExecutorService thread = Executors.newSingleThreadScheduledExecutor(); Runnable run = new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(null, "Open"); } }; thread.scheduleWithFixedDelay(run, 0, 15, TimeUnit.SECONDS);
Esse tem shutdown. Fiz uns testes e não deu nenhum problema, aparentemente.

“Eu odeio trabalhar com Threads. Malditas Threads!”

E

leo_mf:
Bom pessoal para quem gosta de mexer com Thread, tenho uma boa prática para vocês.

ScheduledExecutorService thread = Executors.newSingleThreadScheduledExecutor(); Runnable run = new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(null, "Open"); } }; thread.scheduleWithFixedDelay(run, 0, 15, TimeUnit.SECONDS);
Esse tem shutdown. Fiz uns testes e não deu nenhum problema, aparentemente.

“Eu odeio trabalhar com Threads. Malditas Threads!”

Cuidado - o nome “thread” que você deu ao ExecutorService é realmente “misleading” (enganador).

Acho que pior que comentários incorretos são nomes enganadores para variáveis.

Um ExecutorService não é e nunca vai ser uma thread. Objetos cujas classes implementam ExecutorService, como o próprio nome indica, servem para solicitar a execução de comandos, que casualmente podem ser associados a threads, ou não, conforme a implementação do ExecutorService. Você poderia ter um ExecutorService que rodasse as coisas na mesma thread do programa principal.

L

Senhor, entanglement

Desculpe por isso, prometo que nunca mais vai acontecer.

Arrumei o código de acordo com seu comentário.

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); Runnable thread = new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(null, "Open"); } }; scheduledExecutorService.scheduleWithFixedDelay(thread, 0, 15, TimeUnit.SECONDS);

Magoei com isso :lol: . Não precisava falar assim.

Criado 24 de novembro de 2010
Ultima resposta 24 de nov. de 2010
Respostas 11
Participantes 4