Swing线程机制
首先swing是单线程的,这个是这篇文章的前提,也是意义所在,当swing界面程序启动的时候,会启动3个进程,
1、主线程
2、系统工具包线程:负责捕获操作系统事件,然后将事件转换成swing的事件,然后发送到事件派发线程EDT
3、事件派发线程(EDT):将事件派发到各个组件,并负责调用绘制方法更新界面
所有的事件,例如键盘,鼠标事件,都会由工具包线程转换成swing事件,然后放到事件队列EventQueue中,而这个EventQueue的派发机制是由EDT来管理的。
所以任何修改组件状态的方法都应该在EDT中执行,包括构造方法。Swing这样的构造原理经常会造成的情况就是,在EDT中执行长时间的事件,使 EDT不能及时响应更新界面的事件,就是所说的界面卡住,这种不光是新手就是比较熟练的程序员也会犯的一个错误。所以必须避免在EDT中执行长时间的操作,而避免的方法就是多线程,启动另外的线程来处理冗长的操作,比如操作数据库,读写文件等,在这过程中可能要更新界面来给用户以提示,比如显示一个进度条,过一段事件更新一下界面,但是在EDT以外的线程中更新界面都是无效的,这在前面已经说过,要更新界面就要将对界面的更新操作放到EDT中,但是事件又是在另外的线程中执行的,要解决这个问题就要使用SwingUtilities提供的一个方法了 invokeLater,
Java代码
1. public void actionPerformed(ActionEvent e){
2. new Thread(new Runnable(){
3. //do something
4. SwingUtilities.invokeLater(new Runnable(){
5. pulic void run(){
6. //update the GUI
7. }
8. });
9. }).start;
10. }
这个方法的作用就是将一个更新界面的任务放到EDT中,EDT会在适当的时候进行调用以更新界面。invokeLater负责创建一个含有Runnable的特定事件,并让其在EDT中排队等待调用,当被调用时就会运行Runnable中的run方法进行派发。
invokeLater和invokeAndWait的区别
与invoikeLater一样,invokeAndWait也把可运行对象排入事件派发线程的队列中,invokeLater在把可运行的对象放入队列后就返回,而invokeAndWait一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息,则invokeAndWait方法是很有用的。
一般我们用到invokeLater,都是为了执行事件派发线程中的代码,将一段更新UI事件的代码派发到EventQueue中,但是我们可以从事件派发线程中调用invokeLater,却不能从事件派发线程中调用invokeAndWait,下面我们用代码来例证它们的不同:
SwingConsole.java文件:
Java代码
package swing.utilities;
import javax.swing.*;
public class SwingConsole {
public static void run(final JFrame f, final int width, final int height){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width, height);
f.setVisible(true);
}
});
}
}
TestAction.java文件:
Java代码
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import swing.utilities.SwingConsole;
public class TestAction extends JFrame {
private static final long serialVersionUID = -7462155330900531124L;
private JButton jb1 = new JButton("确定");
private JTextField txt = new JTextField(10);
public TestAction() {
jb1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String name = ((JButton) e.getSource()).getText();
txt.setText(name);
}
});
setLayout(null);
add(txt);
add(jb1);
txt.setBounds(50, 100, 200, 30);
jb1.setBounds(270, 100, 70, 30);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
SwingConsole.run(new TestAction(), 500, 500);
}
});
}
}
我们在启动main线程的时候就把整个SwingConsole派发到EventQueue中,而本身SwingConsole已经处在EventQueue中,我们调用invokeLater 没问题,运行正常!
再看我们修改之后的:
SwingConsole.java文件:
Java代码
package swing.utilities;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
public class SwingConsole {
public static void run(final JFrame f, final int width, final int height){
try {
SwingUtilities.invokeAndWait(new Runnable(){
public void run(){
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width, height);
f.setVisible(true);
}
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
TestAction.java文件:
与前面一样
运行结果,出现异常:Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
在这里,我们把SwingConsole中的invokeLater改成了invokeAndWait,而之前SwingConsole已经处在EventQueue中了。
所以我们可以总结出它们的不同:可以从事件派发线程中调用invokeLater,却不能从事件派发线程中调用invokeAndWait,从事件派发线程调用invokeAndWait的问题是:invokeAndWait锁定调用它的线程,直到可运行对象从事件派发线程中派发出去并且该可运行的对象的run方法激活,如果从事件派发线程调用invoikeAndWait,则会发生死锁的状况,因为invokeAndWait正在等待事件派发,但是,由于是从事件派发线程中调用invokeAndWait,所以直到invokeAndWait返回后事件才能派发。
在这里我们还可以看到,在main函数里,我们在一开始就把整个操作都置于EventQueue中,这样虽然安全,但是不适合新手,因为新手很容易犯刚才那样的错误,一不小心就用了invokeAndWait而产生死锁。对于swing中的线程,我也还没有找到理想的处理机制,所以暂时就先到此,以后有经验才跟大家分享吧。
link:http://www.iteye.com/topic/468236
分享到:
相关推荐
理解并正确使用Swing线程机制对于开发高效且响应迅速的Swing应用程序至关重要。通过在适当线程上执行适当的操作,可以避免性能问题和线程安全问题,从而提升应用的整体质量。因此,当涉及到UI组件的更新或需要执行...
总的来说,理解和正确使用Swing线程机制是构建高效、响应迅速的Java GUI应用程序的基础。遵循线程规则,确保UI操作在EDT中进行,而耗时任务在单独的线程中执行,可以避免界面卡死,提升用户体验。
Swing线程机制是Swing库中的关键概念,它确保了所有对Swing组件的操作都在正确的线程——事件分发线程(Event Dispatch Thread,简称EDT)上执行,以避免线程安全问题和界面更新不一致的情况。`SwingUtilities....
Java Swing线程是Java GUI应用程序开发中的核心概念,特别是在创建响应迅速、稳定的应用时。Swing API设计为单线程模型,这意味着所有对Swing组件的修改和操作必须在同一个线程中完成,即Swing线程(AWT事件分派线程...
8. **Swing线程机制** - AWT/Swing组件不是线程安全的,所有的GUI更新应在Event Dispatch Thread(EDT)中进行,以避免线程冲突。 通过学习和实践“精通Java Swing程序设计”中的实例,读者可以深入了解Swing的...
首先,要实现下雪效果,我们需要理解Swing的事件处理机制。Swing是基于事件驱动的,意味着用户的操作,如点击按钮或移动窗口,会触发特定的事件。这些事件由事件调度线程(Event Dispatch Thread, EDT)处理,EDT...
本文将深入了解 Swing 线程的工作机制,并介绍如何使用 SwingWorker 来解决常见的问题。 一、Swing 线程的工作机制 在 Swing 中,所有的 GUI 组件都是在一个单独的线程中执行的,这个线程被称为 Event Dispatch ...
Swing线程基础是Java GUI编程中的重要概念,特别是对于使用Swing库构建的应用程序而言。Swing设计遵循单一线程原则,确保图形用户界面(GUI)的稳定性和响应性。以下是Swing线程基础的详细说明: 1. **初始化线程 ...
【基于Swing的多线程聊天室】是一个Java应用程序,它利用了Swing库来构建图形用户界面(GUI)并采用多线程技术实现多用户之间的实时通信。Swing是Java Standard Edition(Java SE)的一部分,提供了丰富的组件库用于...
### 你所不知道的五件事—改进Swing ...无论是通过Substance提供的外观定制能力,还是SwingX中强大的组件库,亦或是对Swing线程机制的深入理解,都能够帮助开发者创建出更加现代化、高效的Swing应用。
在本项目中,“swing界面socket多线程聊天室”是一个基于Java Swing的客户端-服务器通信应用,它利用TCP协议来实现实时的聊天功能。这个系统不仅提供了群聊和私聊的功能,还允许用户发送文件,并且具备用户登录与...
在本项目"基于Java Swing的多线程电梯调度模拟"中,我们主要探讨的是如何利用Java的多线程特性来实现一个复杂的系统——电梯调度。这个任务是在操作系统课程中的一个典型作业,它要求开发者模拟真实世界中的电梯运行...
通过阅读和分析源码,可以了解Java的事件驱动编程、线程同步机制(如synchronized关键字和wait/notify方法),以及如何将GUI组件与业务逻辑结合。此外,也可以锻炼到问题解决和调试技巧,这对于任何编程学习者来说都...
在Java编程领域,Swing、线程和网络编程是三个重要的子领域,它们共同构建了丰富的应用程序基础。Swing主要用于创建图形用户界面(GUI),线程则是多任务处理的核心,而网络编程则允许程序通过互联网进行通信。让...
Java提供了多种机制来实现线程间的通信,包括使用wait(), notify()和notifyAll()方法,以及使用synchronized关键字控制并发访问共享资源。这些方法都定义在java.lang.Thread类中。 1. **wait(), notify()和...
此外,Swing的Event Dispatch Thread (EDT)机制保证了所有的界面更新都在同一线程中执行,避免了界面卡顿和不一致的现象。 项目的实现可能包括以下几个步骤: 1. 创建Swing UI,包含红包列表展示区、抢红包按钮等...
线程间通信可能涉及Java的synchronized关键字、wait()、notify()等机制,以确保数据的一致性和安全性。 4. **网络编程**:Java的`java.net`包提供了网络编程所需的基础类,如Socket和ServerSocket。在聊天室应用中...
尽管缺少源代码,我们可以推断出这个JavaSwing应用涉及到的技术和概念,包括图形用户界面设计、事件处理、多线程、网络编程(如果适用)、游戏逻辑实现以及可能的数据持久化。对于想要学习JavaSwing或者想了解如何...
其次,Java的多线程机制在游戏中扮演了关键角色。游戏通常需要同时处理多个任务,如玩家输入、游戏逻辑更新、画面渲染等。Java中的Thread类和Runnable接口可以用来创建和管理这些并发执行的任务。开发者可以通过研究...