Java Swing开发中的线程安全

Java Swing开发中的线程安全,第1张

SwingAPI的设计目标是强大 灵活和易用 非凡地 我们希望能让程序员们方便地建立新的Swing组件 不论是从头开始还是通过扩展我们所提供的一些组件 出于这个目的 我们不要求Swing组件支持多线程访问 相反 我们向组件发送请求并在单一慎李线程中执行请求 本文讨论线程和Swing组件 目的不仅是为了帮助你以线程安全的方式使用SwingAPI 而且解释了我们为什么会选择现在这样的线程方案 本文包括以下内容

单线程规则 Swing线程在同一时刻仅能被一个线程所访问 一般来说 这个线程是事件派发线程 规则的例外 有些 *** 作保证是线程安全的 事件分发 假如你需要从事件处理或绘制代码以外的地方访问UI 那么你可以使用SwingUtilities类的invokeLater要求在事件派发线程中执行某些代码 这个方法会立即返回 不会等待代码执行完毕 invokeAndWait行为与invokeLater类似 除了这个方法会等待代码执行完毕 一般地 你可以用invokeLater来代替这个方法 下面是一些使用这几个API的例子 请同时参阅《TheJavaTutorial》中的 BINGOexample 尤其是以下几个类 CardWindow ControlPane Player和OverallStatusPane

使用invokeLater方法你可以从任何线程调用invokeLater方法以请求事件派发线程运行特定代码 你必须把要运行的代码放到一个Runnable对象的run方法中 并将此Runnable对象设为invokeLater的参数 invokeLater方法会立即返回 不等待事件派发线程执行指定代码 这是一个使用invokeLater方法的例子

 RunnabledoWorkRunnable=newRunnable }

SwingUtilities invokeLater使用invokeAndWait方法invokeAndWait方法和invokeLater方法很相似 除了invokeAndWait方法会等事件派发线程执行了指定代码才返回 在可能的情况下 你应该尽量用invokeLater来代替invokeAndWait 假如你真的要使用invokeAndWait 请确保调用invokeAndWait的线程不会在调用期间持有任何其他线程可能需要的锁

这是一个使用invokeAndWait的例子

 voidshowHelloThereDialogthrowsException }裤滑SwingUtilities invokeAndWait}

类似地 假设一个线程需要对GUI的状态进行存取 比如文本域的内容 它的代码可能类似这样

 voidprintTextField throwsException }SwingUtilities invokeAndWaitSystem out println}

假如你能避免使用线程 最好这样做 线程可能难于使用 并使得程序的debug更困难 一般来说 对于严格意义下的GUI工作 线程是不必要的 比如对组件属性的更新 不管怎么说 有时候线程是必要的 下列情况是使用线程的一些典型情况 执行一项费时的任务而不必将事件派发线程锁定 例子包括执行大量计算的情况 会导致大量类被装载的情况 和为网络或磁盘I/O而阻塞的情况 重复地执行一项 *** 作 通常在两次 *** 作间间隔一个预定的时间周期 要等待来自客户的消息 你可以使用两个类来帮助你实现线程 SwingWorker 创建一个后台线程来执行费时的 *** 作 Timer 创建一个线程来执行或多次执行某些代码 在两次执行间间隔用户定义的延迟 使用SwingWorker类SwingWorker类在SwingWorker java中实现 这个类并不包宽纯迟含在Java的任何发行版中 所以你必须单独下载它 SwingWorker类做了所有实现一个后台线程所需的肮脏工作 虽然许多程序都不需要后台线程 后台线程在执行费时的 *** 作时仍然是很有用的 它能提高程序的性能观感

SwingWorkersanexampleofusingSwingWorker 要使用SwingWorker类 你首先要实现它的一个子类 在子类中 你必须实现construct方法还包含你的长时间 *** 作 当你实例化SwingWorker的子类时 SwingWorker创建一个线程但并不启动它 你要调用你的SwingWorker对象的start方法来启动线程 然后start方法会调用你的construct方法 当你需要construct方法返回的对象时 可以调用SwingWorker类的get方法 这是一个使用SwingWorker类的例子

  //在main方法中 finalSwingWorkerworker=newSwingWorker }worker start //在动作事件处理方法中 JOptionPane showMessageDialog)

当程序的main方法调用start方法 SwingWorker启动一个新的线程来实例化ExpensiveDialogComponent main方法还构造了由一个窗口和一个按钮组成的GUI 当用户点击按钮 程序将阻塞 假如必要 阻塞到ExpensiveDialogComponent创建完成 然后程序显示一个包含ExpensiveDialogComponent的模式对话框 你可以在MyApplication java找到整个程序 使用Timer类Timer类通过一个ActionListener来执行或多次执行一项 *** 作 你创建定时器的时候可以指定 *** 作执行的频率 并且你可以指定定时器的动作事件的监听者 启动定时器后 动作监听者的actionPerformed方法会被调用来执行 *** 作 定时器动作监听者定义的actionPerformed方法将在事件派发线程中调用 这意味着你不必在其中使用invokeLater方法 这是一个使用Timer类来实现动画循环的例子

 publicclassAnimatorApplicationTimer extendsJFrameimplementsActionListener publicvoidstartAnimationelse } publicvoidstopAnimation publicvoidactionPerformed }

在一个线程中执行所有的用户界面代码有这样一些优点 组件开发者不必对线程编程有深入的理解 像ViewPoint和Trestle这类工具包中的所有组件都必须完全支持多线程访问 使得扩展非常困难 尤其对不精通线程编程的开发者来说 最近的一些工具包如SubArctic和IFC 都采用和Swing类似的设计 事件以可预知的次序派发 invokeLater排队的runnable对象从鼠标和键盘事件 定时器事件 绘制请求的同一个队列派发 在一些组件完全支持多线程访问的工具包中 组件的改变被变化无常的线程调度程序穿插到事件处理过程中 这使得全面测试变得困难甚至不可能 更低的代价 尝试小心锁住临界区的工具包要花费实足的时间和空间在锁的治理上 每当工具包中调用某个可能在客户代码中实现的方法时 工具包都要保存它的状态并释放所有锁 以便客户代码能在必要时获得锁 当控制权交回到工具包 工具包又必须重新抓住它的锁并恢复状态 所有应用程序都不得不负担这一代价 即使大多数应用程序并不需要对GUI的并发访问 这是的SubArcticJavaToolkit的对在工具包中支持多线程访问的问题的描述 我们的基本信条是 当设计和建造多线程应用程序 尤其是那些包括GUI组件的应用程序时 必须保证极端小心 线程的使用可能会很有欺骗性 在许多情况下 它们表现得能够极好的简化编成 使得设计 专注于单一任务的简单自治实体 成为可能 在一些情况下它们的确简化了设计和编码 然而 在几乎所有的情况下 它们都使得调试 测试和维护的困难大大增加甚至成为不可能 无论大多数程序员所受的练习 他们的经验和实践 还是我们用来帮助自己的工具 都不是能够用来对付非决定论的 例如 全面测试在bug依靠于时间时是几乎不可能的 尤其对于Java来说 一个程序要运行在许多不同类型的机器的 *** 作系统平台上 并且每个程序都必须在抢先和非抢先式调度下都能正常工作 由于这些固有的困难 我们力劝你三思是否绝对有使用线程的必要 尽管如此 有些情况下使用线程是必要的 所以subArctic提供了一个线程安全的访问机制

lishixinzhi/Article/program/Java/gj/201311/27616

Java是一种跨平台的 解释型语言 Java 源代码编译中间 字节码 存储于class文件中 Class文件是一种字节码形式的中间代码 该字节码中包括了很多源代码的信息 例如变量名 方法名等 因此 Java中间代码的反编译就变得非常容易 目前市场上有许多免费的 商用的反编译软件 都能够生成高质量的反编译后的源代码 所以 对开发人员来说 如何保护Java程序就变成了一个非常重要的挑战 本文首先讨论了保护Java程序的基本方法 然后对代码混淆问题进行深入研究 最后结合一个实际的应用程序 分析如何在实践中渣扮保护Java程序 反编译成为保护Java程序的最大挑战 通常C C++等编程语言开发的程序都被编译成目标代码 这些目标代码都是本机丛纳器的二进制可执行代码 通常所有的源文件被编译 链接成一个可执行文件 在这些可执行文件中 编译器删除了程序中的变量名称 方法名称等信息 这些信息往往是由内存地址表示 例如如果需要使用一个变量 往往是通过这个变量的地址来访问的 因此 反编译这些本地的目标代码就是非常困难的 Java语言的出现 使得反编译变得非常容易而有效 原因如下 由于跨平台的需求 Java的指令集比较简单而通用 较容易得出程序的语义信息 Java编译器将每一个类编译成一个单独的文件 这也简化了反编译的工作 Java 的Class文件中 仍然保留所有的方法名称 变量名称 并且通过这些名称来访问变量和方法 这些符号往往带有许多语义信息 由于Java程序自身的特点 对于不经过处理的Java程序反编译的效果非常好 目前 市场上有许多Java的反编译工具 有免费的 也有商业使用的 还有的是开放源代码的 这些工具的反编译速度和效果都非常不错 好的反编译软件 能够反编译出非常接近源代码的程序 因此 通过反编译器 黑客能够对这些程序进行更改 或者复用其中的程序 因此 如何保护Java程序不被反编译 是非常重要的一个问题 常用的保护技术 由于Java字节码的抽象级别较高 因此它们较容易被反编译 本节介绍了几种常用的方法 用于保护Java字节码不被反编译 通常 这些方法不能够绝对防止程序被反编译 而是加大反编译的难度而已 因为这些方法都有自己的使用环境和弱点 隔离Java程序 最简单的方法就是让用户不能够访问到Java Class程序 这种方法是最根本的方法 具体实现有多种方式 例如 开发人员可以将关键的Java Class放在服务器端 客户端通过访问服务器的相关接口来获得服务 而不是直接访问Class文件 这样黑客就没有办法反编译Class文件 目前 通过接口提供服务的标准和协议也越来越多 例如 HTTP Web Service RPC等 但是有很多应用都不适合这种保护方式 例如对于单机运行的程序就无法隔离Java程序 这种保护方式见图 所示   图 隔离Java程序示意图  如郑灶 对Class文件进行加密 为了防止Class文件被直接反编译 许多开发人员将一些关键的Class文件进行加密 例如对注册码 序列号管理相关的类等 在使用这些被加密的类之前 程序首先需要对这些类进行解密 而后再将这些类装载到JVM当中 这些类的解密可以由硬件完成 也可以使用软件完成 在实现时 开发人员往往通过自定义ClassLoader类来完成加密类的装载(注意由于安全性的原因 Applet不能够支持自定义的ClassLoader) 自定义的ClassLoader首先找到加密的类 而后进行解密 最后将解密后的类装载到JVM当中 在这种保护方式中 自定义的ClassLoader是非常关键的类 由于它本身不是被加密的 因此它可能成为黑客最先攻击的目标 如果相关的解密密钥和算法被攻克 那么被加密的类也很容易被解密 这种保护方式示意图见图   图 对Class文件进行加密示意图 转换成本地代码 将程序转换成本地代码也是一种防止反编译的有效方法 因为本地代码往往难以被反编译 开发人员可以选择将整个应用程序转换成本地代码 也可以选择关键模块转换 如果仅仅转换关键部分模块 Java程序在使用这些模块时 需要使用JNI技术进行调用 当然 在使用这种技术保护Java程序的同时 也牺牲了Java的跨平台特性 对于不同的平台 我们需要维护不同版本的本地代码 这将加重软件支持和维护的工作 不过对于一些关键的模块 有时这种方案往往是必要的 为了保证这些本地代码不被修改和替代 通常需要对这些代码进行数字签名 在使用这些本地代码之前 往往需要对这些本地代码进行认证 确保这些代码没有被黑客更改 如果签名检查通过 则调用相关JNI方法 这种保护方式示意图见图 代码混淆   图 转换成本地代码示意图 代码混淆是对Class文件进行重新组织和处理 使得处理后的代码与处理前代码完成相同的功能(语义) 但是混淆后的代码很难被反编译 即反编译后得出的代码是非常难懂 晦涩的 因此反编译人员很难得出程序的真正语义 从理论上来说 黑客如果有足够的时间 被混淆的代码仍然可能被破解 甚至目前有些人正在研制反混淆的工具 但是从实际情况来看 由于混淆技术的多元化发展 混淆理论的成熟 经过混淆的Java代码还是能够很好地防止反编译 下面我们会详细介绍混淆技术 因为混淆是一种保护Java程序的重要技术 图 是代码混淆的示意图   图 代码混淆示意图 几种技术的总结 以上几种技术都有不同的应用环境 各自都有自己的弱点 表 是相关特点的比较 混淆技术介绍 表 不同保护技术比较表   到目前为止 对于Java程序的保护 混淆技术还是最基本的保护方法 Java混淆工具也非常多 包括商业的 免费的 开放源代码的 Sun公司也提供了自己的混淆工具 它们大多都是对Class文件进行混淆处理 也有少量工具首先对源代码进行处理 然后再对Class进行处理 这样加大了混淆处理的力度 目前 商业上比较成功的混淆工具包括JProof公司的 stBarrier系列 Eastridge公司的JShrink和的SourceGuard等 主要的混淆技术按照混淆目标可以进行如下分类 它们分别为符号混淆(Lexical Obfuscation) 数据混淆(Data Obfuscation) 控制混淆(Control Obfuscation) 预防性混淆(Prevent Transformation) 符号混淆 在Class中存在许多与程序执行本身无关的信息 例如方法名称 变量名称 这些符号的名称往往带有一定的含义 例如某个方法名为getKeyLength() 那么这个方法很可能就是用来返回Key的长度 符号混淆就是将这些信息打乱 把这些信息变成无任何意义的表示 例如将所有的变量从vairant_ 开始编号 对于所有的方法从method_ 开始编号 这将对反编译带来一定的困难 对于私有函数 局部变量 通常可以改变它们的符号 而不影响程序的运行 但是对于一些接口名称 公有函数 成员变量 如果有其它外部模块需要引用这些符号 我们往往需要保留这些名称 否则外部模块找不到这些名称的方法和变量 因此 多数的混淆工具对于符号混淆 都提供了丰富的选项 让用户选择是否 如何进行符号混淆 数据混淆   图 改变数据访问 数据混淆是对程序使用的数据进行混淆 混淆的方法也有多种 主要可以分为改变数据存储及编码(Store and Encode Transform) 改变数据访问(Access Transform) 改变数据存储和编码可以打乱程序使用的数据存储方式 例如将一个有 个成员的数组 拆开为 个变量 并且打乱这些变量的名字 将一个两维数组转化为一个一维数组等 对于一些复杂的数据结构 我们将打乱它的数据结构 例如用多个类代替一个复杂的类等 另外一种方式是改变数据访问 例如访问数组的下标时 我们可以进行一定的计算 图 就是一个例子 在实践混淆处理中 这两种方法通常是综合使用的 在打乱数据存储的同时 也打乱数据访问的方式 经过对数据混淆 程序的语义变得复杂了 这样增大了反编译的难度 控制混淆 控制混淆就是对程序的控制流进行混淆 使得程序的控制流更加难以反编译 通常控制流的改变需要增加一些额外的计算和控制流 因此在性能上会给程序带来一定的负面影响 有时 需要在程序的性能和混淆程度之间进行权衡 控制混淆的技术最为复杂 技巧也最多 这些技术可以分为如下几类 增加混淆控制 通过增加额外的 复杂的控制流 可以将程序原来的语义隐藏起来 例如 对于按次序执行的两个语句A B 我们可以增加一个控制条件 以决定B的执行 通过这种方式加大反汇编的难度 但是所有的干扰控制都不应该影响B的执行 图 就给出三种方式 为这个例子增加混淆控制   图 增加混淆控制的三种方式 控制流重组 重组控制流也是重要的混淆方法 例如 程序调用一个方法 在混淆后 可以将该方法代码嵌入到调用程序当中 反过来 程 lishixinzhi/Article/program/Java/JSP/201311/19576

零基础学习java可按照这份大纲来进行学习

第一阶段:Java专业基础课程

阶段目标:

1. 熟练掌握Java的开发环境与编程核心知识

2. 熟练运用Java面向对象知识进行程序开发

3. 对Java的核心对象和组件有深入理解

4. 熟练应用JavaAPI相关知识

5. 熟练应用JAVA多线程技术

6. 能综合运用所学知识完成一个项目

知识点:

1、基本数据类型,运算符,数组,掌握基本数据类型转换,运算符,流程控制。

2、数组,排序算法,Java常用API,类和对象,了解类与对象,熟悉常用API。

3、面向对象特性,集合框架,熟悉冲配面向对象三大特性,熟练使用集合框架。

4、IO流,多线程。

5、网络协议,线程运用。

第二阶段:JavaWEB核心课程

阶段目标:

1. 熟练掌握数据库和MySQL核心技术

2. 深入理解JDBC与DAO数据库 *** 作

3. 熟练运用JSP及Servlet技术完成网站后台开发

4. 深入理解缓存,连接池,注解,反射,泛型等知识

5. 能够运用所学知识完成自定义框架

知识点:

1、数据库知识,范式,MySQL配置,命令,建库建表,数据的增删改查,约束,视图,存储过程,函数,触发器,事务,游标,建模工具。

2、深入理解数据库管理系统通用知识及MySQL数据库的使用与管理。为Java后台开发打下坚实基础。Web页面元素,布局,CSS样式,盒模型,JavaScript,jQuery。

3、掌握前端开发技术,掌握jQuery。

4、Servlet,EL表达式,会话跟踪技术,过滤器,FreeMarker。

5、掌握Servlet相关技术,利用Servlet,JSP相关应用技术和DAO完成B/S架构下的应用开发。

6、泛型,反射,注解。

7、掌握JAVA高级应用,利用泛型,注解,枚举完成自己的CRUD框架开发为后续框架学习做铺垫。

8、单点登录,支付功能,项目整合,分页封装熟练运用JSP及Servlet核心知识完成项目实战。

第三阶段:JavaEE框架课程

阶段目标:

1. 熟练运用Linux *** 作系统常见命令及完成环境部署和Nginx服务祥判御器的配置

2. 熟练运用JavaEE三大核心框架:Spring,SpringMVC,MyBatis

3. 熟练运用Maven,并使用SpringBoot进行快速框架搭建

4. 深入理解框架的实现原理,Java底层技术,企业级应用等

5. 使用Shiro,Ztree和Spring,SpringMVC,Mybaits完成企业项目

知识点:

1、Linux安装配置,文件目录 *** 作,VI命令,管理,用户与权限,环境部署,Struts2概述,hiberante概述。

2、Linux作为一个主流的服务器 *** 作系统,是每一个开发工程师必须掌握的重点技术,并且能够熟练运用。

3、SSH的整合,MyBatis,SpringMVC,Maven的使用。

4、了解AOP原理,了解中央控制器原理,掌握MyBatis框架,掌握SSM框架的整合。

5、Shiro,Ztree,项目文档,项目规范,需求分析,原型图设计,数据库设计,工程构建,需求评审,配置管理,BUG修复,项目管理等。

6、独谨岩立自主完成一个中小型的企业级综合项目的设计和整体架构的原型和建模。独立自主完成一个大型的企业级综合项目,并具备商业价值


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12216629.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存