• UI线程中非安全操作与安全操作


    ------------------siwuxie095

       

       

       

       

       

       

       

    工程名:SwingUIThreadSafeTest

    包名:com.siwuxie095.swinguithread

    类名:MyFrame.java

       

       

    工程结构目录如下:

     

       

       

       

       

    代码:

       

    package com.siwuxie095.swinguithread;

       

    import java.awt.BorderLayout;

    import java.awt.EventQueue;

    import java.awt.event.MouseAdapter;

    import java.awt.event.MouseEvent;

       

    import javax.swing.JButton;

    import javax.swing.JFrame;

    import javax.swing.JPanel;

    import javax.swing.JProgressBar;

    import javax.swing.UIManager;

    import javax.swing.UnsupportedLookAndFeelException;

    import javax.swing.border.EmptyBorder;

       

    import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;

       

    //MyFrame 直接继承自 JFrame

    public class MyFrame extends JFrame {

       

    private JPanel contentPane;

       

    /**

    * Launch the application.

    */

     

    public static void main(String[] args) {

     

    EventQueue.invokeLater(new Runnable() {

    public void run() {

    try {

    MyFrame frame = new MyFrame();

    frame.setVisible(true);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    });

     

    }

       

    /**

    * Create the frame.

    */

    public MyFrame() {

     

    try {

    UIManager.setLookAndFeel(new WindowsLookAndFeel());

    } catch (UnsupportedLookAndFeelException e) {

    e.printStackTrace();

    }

     

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setBounds(100, 100, 450, 300);

    contentPane = new JPanel();

    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

    contentPane.setLayout(new BorderLayout(0, 0));

    setContentPane(contentPane);

     

    JProgressBar progressBar = new JProgressBar();

    contentPane.add(progressBar, BorderLayout.NORTH);

     

    JButton btnRun = new JButton("Run");

     

    //为按钮 Run 添加 mouseClicked 事件

    btnRun.addMouseListener(new MouseAdapter() {

    @Override

    public void mouseClicked(MouseEvent e) {

    /*********************************************************

    * 非安全操作(1)

    *

    * 点击 Run 按钮后,该按钮不会弹起,进度条也不会增加,即 界面卡死,没有任何反应

    * 直到 10 秒后,Run 按钮弹起,进度条直接跳到满格,中间的所有过程都没有被展示

    *

    * 出现这种情况的原因:当为鼠标添加的事件触发后,调用 mouseClicked()方法,

    * 该方法也是被当前的UI线程所执行的,一旦UI线程中出现了 类似 sleep(1000) 这样的阻塞方法,

    * 将造成UI线程一直在阻塞的地方等待 ,而不会执行任何界面刷新的工作,这就导致了界面卡死的现象

    *

    * 如果要编写一个响应良好的界面,不能在UI线程中执行非常耗时的操作

    * 如:等待、UI的读写、网络的读写

    *

    * 如果一定要执行等待、或每隔多长时间执行一个特殊的动作,可以使用 Swing Timer 进行操作

    * 如果需要读取大量的网络数据,或读写本地文件,可以创建一个新的线程 SwingWorker

    *********************************************************

    */

     

    // //(1)只需点击一次按钮

    // for (int i = 1; i <= 10; i++) {

    // try {

    // //1 秒进度条增加一格

    // //有异常抛出,用 try catch 捕获

    // Thread.sleep(1000);

    // progressBar.setValue(i*10);

    // } catch (InterruptedException e1) {

    // e1.printStackTrace();

    // }

    // }

     

     

    /*********************************************************

    * 安全操作(2)

    *

    * 在为界面中的元素添加的监听器(各种事件)触发所产生的回调方法

    * 都是由 Swing 的事件派发线程(UI线程)来完成的

    *

    * UI线程中可以非常安全操作任何元素的属性

    * 如:让进度条根据自己的 value 10

    *********************************************************

    */

     

    //(2)需要连续点击按钮

    progressBar.setValue(progressBar.getValue()+10);

     

     

    }

    });

     

    btnRun.setFocusable(false);

    contentPane.add(btnRun, BorderLayout.SOUTH);

    }

       

    }

       

       

       

    将窗体 JFrame 的 LookAndFeel 设定为 Windows

       

       

    在根面板 contentPane 的上方添加一个 JProgressBar,

    下方添加一个 JButton

       

       

    将 JButton 的文本(text)改为 Run,并 Rename 为 btnRun,

    将 focusable 属性设为 false

       

       

    为 JButton 添加 mouseClicked 事件,当点击 Run 按钮时,进度条的增加

       

       

    非安全操作:

       

       

       

    运行程序:

    点击 Run 按钮后,按钮不会弹起,进度条也不会增加,

    界面卡死。直到 10 秒后,Run 按钮才弹起,进度条

    直接跳到满格

       

       

       

    界面卡死的原因:

       

    当为鼠标添加的事件触发后,调用 mouseClicked() 方法,

    该方法也是被当前的 UI 线程所执行的

       

    一旦 UI 线程中出现类似 Thread.sleep(1000); 这样的阻塞方法,将

    造成 UI 线程一直在阻塞处 Thread.sleep(1000); 等待 ,而不会执行

    任何界面刷新的工作,进而导致界面卡死

       

       

       

    安全操作:

       

       

       

    运行程序:

       

       

       

       

       

       

    因界面中元素的监听器(各种事件)触发所产生的回调方法都是

    由 Swing 的事件派发线程(UI 线程)来完成的

       

    「事件派发线程 Event Dispatch Thread,简称 EDT」

       

    所以,如果要编写一个响应良好的界面,不能在 UI 线程中执行非常耗时的操作

       

    如:等待、文件的读写、网络数据的读写

       

     

    如果一定要执行等待、或 每隔一定时间执行一个特殊的动作,可以

    使用 Swing 的 Timer 进行操作

       

       

    如果需要读取大量的网络数据,或 读写本地文件,可以

    使用 Swing 的 SwingWorker 进行操作

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    小程序接入第三方ui库(组件库)
    element ui表格的校验和自定义校验规则
    element ui表格 表头的的特殊处理(换行/jsx风格表头)以及上传组件的一点小问题
    MongoDB 配置本地服务
    乙方渗透测试之Fuzz爆破
    SSRF漏洞挖掘经验
    SQL注入绕过技巧总结
    Xss Bypass备忘录
    bilibili存储型xss (绕过长度限制打乱顺序限制)
    XSS攻击常识及常见的XSS攻击脚本汇总
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6674081.html
Copyright © 2020-2023  润新知