Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 405|回复: 0

Java线程—如何解决Swing的单线程问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-28 04:23:39 | 显示全部楼层 |阅读模式

    《》Swing线程机制

    首先swing是单线程的,这个是这篇文章的前提,也是意义所在,当swing界面程序启动的时候,会启动3个进程,

    1、主线程

    2、系统工具包线程:负责捕获操作系统事件,然后将事件转换成swing的事件,然后发送到事件派发线程EDT

    3、事件派发线程(EDT):将事件派发到各个组件,并负责调用绘制方法更新界面


    所有的事件,例如键盘,鼠标事件,都会由工具包线程转换成swing事件,然后放到事件队列EventQueue中,而这个EventQueue的派发机制是由EDT来管理的。

                                              EDT管理队列

    所以任何修改组件状态的方法都应该在EDT中执行,包括构造方法。Swing这样的构造原理经常会造成的情况就是,在EDT中执行长时间的事件,使EDT不能及时响应更新界面的事件,就是所说的界面卡住,这种不光是新手就是比较熟练的程序员也会犯的一个错误。所以必须避免在EDT中执行长时间的操作,而避免的方法就是多线程,启动另外的线程来处理冗长的操作,比如操作数据库,读写文件等,在这过程中可能要更新界面来给用户以提示,比如显示一个进度条,过一段时间更新一下界面,但是在EDT以外的线程中更新界面都是无效的,这在前面已经说过,要更新界面就要将对界面的更新操作放到EDT中,但是事件又是在另外的线程中执行的,要解决这个问题就要使用SwingUtilities提供的两个静态方法了 invokeLater,invokeAndWait

    举例:

    invokeLater的使用

    class GetInfoThread extends Thread {
    
      Test applet;
      Runnable runx;
      int value;
    
      public GetInfoThread(final Test applet) {
       this.applet = applet;
       runx = new Runnable() {
        public void run() {
         JProgressBar jpb = applet.getProgressBar();
         jpb.setValue(value);
        }
       };
      }
    
       public void run() {
        while (true) {
         try {
          Thread.sleep(500);
          value = (int) (Math.random() * 100);
          System.out.println(value);
          SwingUtilities.invokeLater(runx);
         } catch (InterruptedException e) {
          e.printStackTrace();
         }
        }
       }
      }

     

    《》invokeAndWaitinvokeLater的区别

    与invoikeLater一样,invokeAndWait也把可运行对象排入事件派发线程的队列中,invokeLater在把可运行的对象放入队列后就返回,而invokeAndWait一直等待直到提交的run方法执行完毕后才返回。如果操作2,必须得等到操作1完毕之后,才能够执行的话,则invokeAndWait方法是很有用的,那么我们就用invokeAndWait将操作1提交,之后再执行操作2就行了;

    invokeAndWait的使用

    class GetInfoThread extends Thread {
       
       Runnable getValue,setValue;
       int value,currentValue;
    
       public GetInfoThread(final Test applet){
    
       getValue=new Runnable(){
       public void run(){
        JProgressBar pb=applet.getProgressBar();
        currentValue=pb.getValue();
        }
       };
    
       setValue=new Runnable(){
        public void run(){
         JProgressBar pb=applet.getProgressBar();
         pb.setValue(value);
        }
       }
       }
    
       public void run(){
        while(true){
        try{
        Thread.currentThead().sleep(500);
        value=(int)(Math.random()*100);
        try{
        SwingUtilities.invokeAndWait(getValue);//直到getValue可运行的run方法返回后才返回
          }catch(Exception ex){
          }
          if(currentValue!=value){
          SwingUtilities.invokeLater(setValue);
          }
         }
         }catch(Exception ex){
          }
        }
       }

     

    注意:这两个方法的作用只是将一个更新界面的Runnable任务提交给EDT线程,EDT会在适当的时候进行调用以更新界面。

    《》这就解决了Swing的线程不安全的问题

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-1 17:00 , Processed in 0.057523 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表