Java线程模子缺陷研究[Java编程]
本文“Java线程模子缺陷研究[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
Java 编程语言的线程模子大概是此语言中最柔弱的部份.它完好不合适实际复杂程序的要求,并且也完好不是面向对象的.本文倡议对 Java 语言举行庞大改正和增补,以办理这些问题.
Java 语言的线程模子是此语言的一个最难另人称心的部份.固然 Java 语言本身就支持线程编程是件功德,但是它对线程的语法和类包的支持太少,只能实用于极小型的利用环境.
关于 Java 线程编程的大大都书籍都长篇累牍地指出了 Java 线程模子的缺陷,并供应了办理这些问题的急救包(Band-Aid/邦迪创可贴)类库.我称这些类为急救包,是因为它们所能办理的问题本应是由 Java 语言本身语法所包含的.从长远来看,以语法而不是类库办法,将能产生更高效的代码.这是因为编译器和 Java 虚拟器 (JVM) 能一同优化程序代码,而这些优化关于类库中的代码是很难或无法实现的.
Allen Holub 指出,在我的《Taming Java Threads 》(请参阅 参考资料 )书中以及本文中,我进一步倡议对 Java 编程语言本身举行一些改正,以使得它可以真正办理这些线程编程的问题.本文和我这本书的主要辨别是,我在撰写本文时举行了更多的考虑, 所以对书中的提议加以了提高.这些倡议只是尝试性的 -- 只是我个人对这些问题的设法,并且实现这些设法需求举行大量的工作以及同行们的评价.但这是毕竟是一个初阶,我有意为办理这些问题成立一个专门的工作组,假如您感爱好,请发 e-mail 到 threading@holub.com .一旦我真正着手举行,我就会给您发告诉.
这里提出的倡议是非常斗胆的.有些人倡议对 Java 语言标准 (JLS)(请参阅参考资料 )举行渺小和少量的改正以办该当前模糊的 JVM 行为,但是我却想对其举行更为完好的改良.
在实际草稿中,我的很多倡议包含为此语言引入新的关键字.固然普通要求不要冲破一个语言的现有代码是精确的,但是假如该语言的并非要保持不变以至于过期的话,它就必须能引入新的关键字.为了使引入的关键字与现有的标识符不产生冲突,经过细心考虑,我将利用一个 ($) 字符,而这个字符在现有的标识符中是不法的.(比方,利用 $task,而不是 task).此时需求编译器的号令行开关供应支持,能利用这些关键字的变体,而不是忽视这个美圆标记.
task(任务)的概念
Java 线程模子的根本问题是它完好不是面向对象的.面向对象 (OO) 计划人员根本不按线程角度考虑问题;他们考虑的是同步 信息 异步 信息(同步信息被当即处理 -- 直到信息处理完成才返回消息句柄;异步信息收到后将在后台处理一段时间 -- 而早在信息处理完毕前就返回消息句柄).Java 编程语言中的 Toolkit.getImage() 办法就是异步信息的一个好例子. getImage() 的消息句柄将被当即返回,而没必要等到整个图象被后台线程取回.
这是面向对象 (OO) 的处理办法.但是,如前所述,Java 的线程模子是非面向对象的.一个 Java 编程语言线程实际上只是一个run() 历程,它调用了别的的历程.在这里就根本没有对象、异步或同步信息以及别的概念.
关于此问题,在我的书中深化谈论过的一个办理办法是,利用一个Active_object. active 对象是可以接纳异步恳求的对象,它在接纳到恳求后的一段时间内今后台方法得以处理.在 Java 编程语言中,一个恳求可被封装在一个对象中.比方,你可以把一个通过 Runnable 接口实现的实例传送给此 active 对象,该接口的 run() 办法封装了需求完成的工作.该 runnable 对象被此 active 对象排入到行列中,当轮到它履行时,active 对象利用一个后台线程来履行它.
在一个 active 对象上运行的异步信息实际上是同步的,因为它们被一个单一的服务线程按次序从行列中取出并履行.因此,利用一个 active 对象以一种更为历程化的模子可以消除大大都的同步问题.
在某种意义上,Java 编程语言的整个 Swing/AWT 子系统是一个 active 对象.向一个 Swing 行列传送一条讯息的唯一安全的途径是,调用一个近似SwingUtilities.invokeLater() 的办法,这样就在 Swing 事件行列上发送了一个 runnable 对象,当轮到它履行时, Swing 事件处理线程将会处理它.
那么我的第一个倡议是,向 Java 编程语言中加入一个task (任务)的概念,从而将active 对象集成到语言中.( task的概念是从 Intel 的 RMX 操作系统和 Ada 编程语言鉴戒过来的.大大都及时操作系统都支持近似的概念.)
一个任务有一个内置的 active 对象分发程序,并自动管理那些处理异步信息的全部机制.
定义一个任务和定义一个类基本相同,差别的只是需求在任务的办法前加一个asynchronous 修饰符来指导 active 对象的分配程序在后台处理这些办法.
全部的写恳求都用一个dispatch() 历程调用被放在 active-object 的输入行列中列队.在后台处理这些异步信息时呈现的任何非常 (exception) 都由 Exception_handler 对象处理,此 Exception_handler 对象被传送到 File_io_task 的构造函数中.
这种基于类的处理办法,其主要问题是太复杂了 -- 关于一个这样简单的操作,代码太杂了.向 Java 语言引入$task 和 $asynchronous 关键字后,便可以按下面这样重写从前的代码:
注意,异步办法并没有指定返回值,因为其句柄将被当即返回,而不用等到恳求的操作处理完成后.所以,此时没有公道的返回值.关于派生出的模子,$task 关键字和 class 一样同效: $task 可以实现接口、担当类和担当的别的任务.标有 asynchronous 关键字的办法由 $task 在后台处理.别的的办法将同步运行,就像在类中一样.
$task关键字可以用一个可选的 $error 从句修饰 (如上所示),它表明对任何无法被异步办法本身捕捉的非常将有一个缺省的处理程序.我利用 $ 来代表被抛出的非常对象.假如没有指定 $error 从句,就将打印出一个公道的出错信息(极大概是仓库跟踪信息).
注意,为确保线程安全,异步办法的参数必须是不变 (immutable) 的.运行时系统应通过相关语义来保证这种不变性(简单的复制普通是不够的).
全部的 task 对象必须支持一些伪信息 (pseudo-message).
除了常用的修饰符(public 等), task 关键字还答允受一个 $pooled(n) 修饰符,它招致 task 利用一个线程池,而不是利用单个线程来运行异步恳求. n 指定了所需线程池的大小;必要时,此线程池可以增添,但是当不再需求线程时,它应当缩到本来的大小.伪域 (pseudo-field) $pool_size 返回在 $pooled(n) 中指定的原始 n 参数值.
在《Taming Java Threads 》的第八章中,我给出了一个服务器端的 socket 处理程序,作为线程池的例子.它是关于利用线程池的任务的一个好例子.其基本思绪是产生一个独立对象,它的任务是监控一个服务器端的 socket.每当一个客户机衔接到服务器时,服务器端的对象会从池中抓取一个预先成立的就寝线程,并把此线程设置为服务于客户端衔接.socket 服务器会产出一个额外的客户服务线程,但是当衔接关闭时,这些额外的线程将被删除.
以上是“Java线程模子缺陷研究[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |