• Swing Threading的限制


    一个GUI程序是具有数个thread的,这些thread之中有一个被称为时间派发(event-dispatching) thread。这个thread运行程序中所有与事件有关的回调(callback),如打字游戏中的actionPerformed()与keyPressed()方法。对所有Swing对象的访问都必须发生在此thread中。

    之所以需要这样的原因是Swing并没有用同步来访问本身对象的复杂内在状态。以JSlider对象为例,它有个用来指示slider位置的单一值。如果使用者正在改变此slider的位置,该值可能正位于中间或尚未确定的状态,这样的处理全部都是发生在事件派发thread中。另一个尝试要读取该slider值的thread将无法直接读取,因为此thread可能会因此读到中间状态的值。所以,另一个thread必须安排事件派发thread去读取该值并将值返回给此thread。

    注意,只靠另一个thread同步访问JSlider对象是不够的。Swing的内部机制并不是同步访问,所以两个thread还是同时地在访问slider的内部状态。要记得lock是协同运作的:如果所有的thread都没有尝试取得lock,race condition还是会发生。

    感觉上这样的限制太过强烈:JSlider的值只是单一的变量且可以被轻易地做成volatile。实际上并不是这样。在Swing组件内各种事物的值可能是非常复杂的。许多Swing组件都遵循着mode-view-controller这种design pattern,且在此model被时间派发thread更新的时候从某个thread去访问这些组件是非常危险的。即使是最简单的SWing组件也带有复杂的状态,决不能接受从不是事件派发的thread中调用它们的任何一个method。

    因此,所有对Swing对象的调用都必须从事件派发thread发出。它是Swing用来在内部改变对象状态的thread,只要你对Swing对象的调用都是来自该thread,就不会有race condition。这个规则有以下四个例外:

    1. 还没有显示出的Swing对象可以被任何的thread创建于操作。这代表你可以在任何thread中创建GUI对象,若一旦对象已经显示,它们就仅能由事件派发thread来访问。GUI对象是在它的父frame的show()方法被调用的时候显示的。
    2. repaint()方法可以从任何的thread调用。
    3. invokeLater()方法可以从任何的thread调用。
    4. invokeAndWait()方法可以从任何不是事件派发的thread调用

    -----------------------------------------------------------------------------------------------------

    Swing class已经确保所有的回调都会发生在事件派发thread上。

  • 相关阅读:
    html5学习笔记
    J-Link eclipse Plug-ins install
    SEGGER J-Link install
    如何使用Redis实现分布式锁?
    在Redis里,如何从海量key中查询出某一个固定前缀所有的key?
    (必问)Redis有哪些常用数据类型?
    (必问)Http和Https的区别有哪些?
    Https的传输流程是什么?
    Cookie和Session有什么区别?
    HTTP的状态码有哪些?
  • 原文地址:https://www.cnblogs.com/cuizhf/p/2182229.html
Copyright © 2020-2023  润新知