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:
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.
Um exemplo do uso de Future e Callable está no Javadoc acima.
L
leo_mf
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.
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
ViniGodoy1 like
O método stop() foi deprecated pois ele gera leak de recursos:
Locks de sincronização ficam presos;
Arquivos podem ficar abertos;
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
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!
E
entanglement
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
entanglement
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();
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
entanglement
Exemplo.
packageguj;importjava.awt.BorderLayout;importjava.awt.FlowLayout;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.FutureTask;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JPanel;importjavax.swing.JProgressBar;importjavax.swing.SwingUtilities;classAtualizadorimplementsCallable<Void>{publicAtualizador(JProgressBarprb){this.prb=prb;}@OverridepublicVoidcall()throwsException{while(true){SwingUtilities.invokeLater(newRunnable(){publicvoidrun(){prb.setValue(val++);}});if(val>=100)val=0;Thread.sleep(100);}}privateJProgressBarprb;privateintval=0;}publicclassExemploCallableextendsJFrame{privatestaticfinallongserialVersionUID=1L;privateJPaneljContentPane=null;privateJPanelpnlBotoes=null;privateJButtonbtnIniciar=null;privateJButtonbtnParar=null;privateJProgressBarprbProgresso=null;privateExecutorServiceexecutor;privateFutureTask<Void>future;privateJPanelgetPnlBotoes(){if(pnlBotoes==null){pnlBotoes=newJPanel();pnlBotoes.setLayout(newFlowLayout());pnlBotoes.add(getBtnIniciar(),null);pnlBotoes.add(getBtnParar(),null);}returnpnlBotoes;}privateJButtongetBtnIniciar(){if(btnIniciar==null){btnIniciar=newJButton();btnIniciar.setText("Iniciar!");btnIniciar.addActionListener(newjava.awt.event.ActionListener(){publicvoidactionPerformed(java.awt.event.ActionEvente){btnIniciar.setEnabled(false);future=newFutureTask<Void>(newAtualizador(prbProgresso));executor.execute(future);btnParar.setEnabled(true);}});}returnbtnIniciar;}privateJButtongetBtnParar(){if(btnParar==null){btnParar=newJButton();btnParar.setText("Parar!");btnParar.setEnabled(false);btnParar.addActionListener(newjava.awt.event.ActionListener(){publicvoidactionPerformed(java.awt.event.ActionEvente){btnParar.setEnabled(false);future.cancel(true);btnIniciar.setEnabled(true);}});}returnbtnParar;}privateJProgressBargetPrbProgresso(){if(prbProgresso==null){prbProgresso=newJProgressBar();prbProgresso.setStringPainted(true);}returnprbProgresso;}publicstaticvoidmain(String[]args){// TODO Auto-generated method stubSwingUtilities.invokeLater(newRunnable(){publicvoidrun(){ExemploCallablethisClass=newExemploCallable();thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);thisClass.setVisible(true);}});}publicExemploCallable(){super();initialize();executor=Executors.newCachedThreadPool();}privatevoidinitialize(){this.setSize(300,111);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setContentPane(getJContentPane());this.setTitle("Exemplo Callable");}privateJPanelgetJContentPane(){if(jContentPane==null){jContentPane=newJPanel();jContentPane.setLayout(newBorderLayout());jContentPane.add(getPnlBotoes(),BorderLayout.SOUTH);jContentPane.add(getPrbProgresso(),BorderLayout.CENTER);}returnjContentPane;}}
L
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!”
E
entanglement
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
leo_mf
Senhor, entanglement
Desculpe por isso, prometo que nunca mais vai acontecer.