Já li até alguns tópicos aqui mas não consegui entender direito. Li sobre threads e tal. Li que o Swing não é seguro para threads, e que ele tem uma única thread que é a “thread de despacho de eventos” para fazer as interações com os usuários e atualizar a GUI…Ham? aHDSUAHDOHASDIH Não entendi muito bem o que ele quis dizer com isso. E qual a diferença de eu criar uma classe separada para criar um objeto e executar o método que cria a GUI desse objeto ao inves de eu usar só uma classe, como aquelas de formulários do NetBeans e usar o método:
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Server().setVisible(true);
}
});
}
Vou tentar reformular a pergunta melhor…
A construção da GUI do aplicativo está no método initComponents(). Eu quero saber, qual a diferença de eu usar esse método na mesma classe de initComponents():
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// lembrando que primeiro ele vai chamar o construtor que tem o método initComponents(), configurar os componentes e, depois o método retorna e chama //setVisible()
new Server().setVisible(true);
}
});
Ou de eu usar uma OUTRA CLASSE, instanciar um objeto e colocar o método setVisible() na classe de GUI:
//OUTRA CLASSE
public class OutraClasse {
public static void main( String[] args ) {
ClasseComInitComponents objeto = new ClasseComInitComponents();
}
}
Ou ao invés de usar o “java.awt.EventQueue.invokeLater” como no primeiro exemplo, usar o SwingUtilities.Event.invokeLater()??? Entenderam?
O EventQueue.invokeLater agenda na thread do Swing um comando para que ela execute. Assim você mantém o Swing rodando numa thread só.
Quando você roda diretamente da main thread, é a main thread que está dando o setVisible. Com isso, você passa a ter 2 threads sobre o Swing (a do Swing e a main), ferindo o fato dele não ser multi-thread.
[quote=ViniGodoy]O EventQueue.invokeLater agenda na thread do Swing um comando para que ela execute. Assim você mantém o Swing rodando numa thread só.
Quando você roda diretamente da main thread, é a main thread que está dando o setVisible. Com isso, você passa a ter 2 threads sobre o Swing (a do Swing e a main), ferindo o fato dele não ser multi-thread.[/quote]
Então o correto quando eu tiver uma aplicação com GUI, é sempre eu usar o método invokeLater para dar setVisible() ? Quando você diz main thread, a qual método main você está se referindo, o da classe da GUI ou o da classe que cria a instância? E você sabe a diferença de eu usar o EventQueue ao invés de SwingUtilities? Eu estou com essa dúvida porque no NetBeans quando geramos um JFrame, ele sempre cria esse metodo main com EventQueue.invokeLater com setVisible(), e eu iniciava a classe por ai mesmo, já que tém o método main, mas nos exemplos do livro Java Como Programar, ele sempre cria uma classe com nome “Test” e cria um objeto da classe onde tem a configuração da GUI e chama o setVisible() nessa classe de “Test”. Entendeu?
Se você não estiver na thread do Swing, sim.
Entretanto, num evento de botão, você já estará na thread do Swing. Nesse caso, não será necessário.
Tanto faz. A aplicação Java sempre inicia na thread principal, não interessa a classe que esse main esteja.
Nenhuma. Veja o código do SwingUtilities.invokeLater:
public static void invokeLater(Runnable doRun) {
EventQueue.invokeLater(doRun);
}
Aliás, você também poderia ter lido no Javadoc da classe:
Mas o certo, a partir do main (ou de qualquer outra thread que não seja a do Swing) é sempre usar um método do tipo “InvokeLater” para atualizar qualquer aspecto da interface gráfica - desde tornar uma janela visível, até uma simples atualização de textos num JLabel. São poucos os métodos do Swing que podem ser chamados sem isso e, geralmente, estão documentados. É o caso do método append do JTextArea.
Acho que estou começando a entender…Me tire essas dúvidas por favor, para clarear a minha mente e eu entender melhor.
Uma aplicação de janela de comando, sem GUI, e sem threads declaradas explicitamente. Ela tem quantas threads?
Uma aplicação GUI, sem declarar threads explicitamente, tem quantas threads? As threads dessa aplicação vão variar de acordo com o número de classes? Ou isso não tem nada a ver? Exemplo, eu tenho uma aplicação gui que usa objetos de outras classes.
Deixa eu ver se entendi essa parte. Sempre que eu for atualizar um componente Swing eu uso um InvokeLater, a não ser que eu já esteja na Thread do Swing( Thread de despacho de eventos). E como eu sei que estou na thread do Swing? Eu sei que quando eu estou fazendo uma interação com o usuário, atualizando um components swing em um handler de evento, eu não vou precisar usar invokeLater porque já vou estar na thread do Swing, mas em outros casos? Estou certo nessa afirmação que fiz? Engraçado que você falou que o método append do JTextArea não precisa ser chamado em um invokeLater, mas no livro ele chama exatamente apenas o append dentro de um invokeLater.
A aplicação começa na thread principal.
Quando o Swing inicia, ele inicia a thread do Swing. Portanto, são 2 threads (é por isso que o setVisible não segura a execução do main até que a janela feche).
Se sua aplicação no main não faz nada além de abrir uma jenela, o main finaliza e a thread main finaliza junto, restando apenas a thread do swing.
Isso não tem nada a ver. Threads não são classes, e classes não são threads. E a classe Thread também não é uma thread.
[quote]Deixa eu ver se entendi essa parte. Sempre que eu for atualizar um componente Swing eu uso um InvokeLater, a não ser que eu já esteja na Thread do Swing( Thread de despacho de eventos). E como eu sei que estou na thread do Swing? Eu sei que quando eu estou fazendo uma interação com o usuário, atualizando um components swing em um handler de evento, eu não vou precisar usar invokeLater porque já vou estar na thread do Swing, mas em outros casos? Estou certo nessa afirmação que fiz? Engraçado que você falou que o método append do JTextArea não precisa ser chamado em um invokeLater, mas no livro ele chama exatamente apenas o append dentro de um invokeLater.
[/quote]
Todo método que for disparado por um evento de botão, e os métodos que esse evento chamarem, não importa de que classe, estarão na thread do Swing. Ou seja, tudo que rodar do início do código do botão, até o fim, em qualquer classe, estará nessa thread.
Entendi. Quer dizer que a Thread é a tarefa em si, pode-se dizer que é o objeto que implementa Runnable ou Callable? Ou então é algo abstrato, aquela tarefa que vai executar parelelamente?
Entendi.
Muito obrigado pela explicação, consegui entender bem melhor sobre threads e swing e sobre qual thread é executada quando os aplicativos iniciam.
Thread é a linha de execução. É o processador, rodando seu programa.
Se você tem duas threads, vc tem dois trechos do seu programa rodando paralelamente.
O runnable ou o callable só definem em que trecho essa thread vai começar.
Thread é a linha de execução. É o processador, rodando seu programa.
Se você tem duas threads, vc tem dois trechos do seu programa rodando paralelamente.
O runnable ou o callable só definem em que trecho essa thread vai começar.[/quote]