Olá amiguinhos,
Vou ensinar um esquema que me ajudou por bastante tempo. Controle por iterações no sistema. Um objeto do tipo observador, irá acompanhar as mudanças do sistema.
Vamos lá, crie a seguinte classe, que será nossa interface gráfica principal:
package br.org.testethread;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Principal extends JFrame {
private static final long serialVersionUID = 1L;
public Principal() {
super("Teste Thread");
setSize(150, 150);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = getSize().width;
int h = getSize().height;
int x = (dim.width-w) / 2;
int y = (dim.height-h) / 2;
setLocation(x, y);
JPanel p = new JPanel();
final JLabel lb = new JLabel("0");
final JButton bt = new JButton("Clique aqui!");
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i=0; i < 5000000; i++) {
lb.setText(String.valueOf(i));
}
}
});
p.add(lb);
p.add(bt);
getContentPane().add(p);
}
public static void main(String[] args) {
new Principal().setVisible(true);
}
}

Rode o programa e clique no botão para você ver o que acontece. A interface vai congelar, dependendo do seu processador é claro. Se sua máquina for muito potente, aumente a quantidade de laços. Aqui no meu, tive que deixar em 5 milhões para ficar congelada a tela.
Para resolver esse problema, crie uma classe chamada Observador com a seguinte estrutura:
package br.org.testethread;
import java.util.Observable;
import java.util.Observer;
public class Observador extends Observable implements Runnable {
public Observador(Observer observador) {
// Adiciona o objeto observador a lista de observadores
addObserver(observador);
}
public void run() {
int i;
for (i = 0; i <= 10; i++) {
// Notifica o processamento a cada 10 iterações
if ((i % 10 == 0)) {
notifyObservers(new Integer(i));
setChanged();
}
}
// Notifica fim do processo
notifyObservers(new Boolean(true));
setChanged();
}
}
Já temos a nossa classe do tipo Observer, ela vai observar as alterações dos objetos a cada 10 iterações e vai notificar os observadores. Agora precisamos fazer algumas alterações na nossa classe Principal, ela deverá ficar da seguinte forma:
package br.org.testethread;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
// Adiciona a interface Observer
public class Principal extends JFrame implements Observer {
private static final long serialVersionUID = 1L;
// Cria um objeto do tipo Thread
private Thread processo;
// Declara o label para uso global
private JLabel lb;
public Principal() {
super("Teste Thread");
setSize(150, 150);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = getSize().width;
int h = getSize().height;
int x = (dim.width - w) / 2;
int y = (dim.height - h) / 2;
setLocation(x, y);
JPanel p = new JPanel();
lb = new JLabel("0");
final JButton bt = new JButton("Clique aqui!");
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// metodo que vai criar uma nova thread
executaProcesso();
}
});
p.add(lb);
p.add(bt);
getContentPane().add(p);
}
public static void main(String[] args) {
new Principal().setVisible(true);
}
private void executaProcesso() {
if (processo == null) {
processo = new Thread(new Observador(this));
processo.start();
} else {
JOptionPane.showMessageDialog(this,
"O processo ainda está em execução!");
}
}
public void update(Observable o, Object arg) {
if (arg instanceof Integer) {
// O laco foi transportado para essa parte
for (int i = 0; i < 5000000; i++) {
lb.setText(String.valueOf(i));
}
} else if (arg instanceof Boolean) {
if (((Boolean) arg).booleanValue()) {
JOptionPane.showMessageDialog(this,
"Processo terminado!");
}
}
}
}
Agora clique no botão para você ver. Você vai acompanhar a incrementação sem que a tela congele. Enquanto ele continua incrementando, experimente clicar no botão novamente para ver o que acontece. Ele te alerta que o processo ainda não terminou. A interface Observer vai "observar" o processo de acordo com a classe Observador. Não é muito difícil de entender, mas você precisa ter uma noção básica de Thread para entender.
Não testei esse esquema para Web, quem quiser testar e comentar aqui, seria legal. Mas acredito que para Web o esquema é meio diferente.
Enjoy...
0 comentários:
Postar um comentário