专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » java多线程:java线程的缺陷 »正文

java多线程:java线程的缺陷

来源: 发布时间:星期三, 2008年12月17日 浏览:85次 评论:0
Allen Holub 指出Java 编程语言线程模型可能是此语言中最薄弱部分它完全不适合实际复杂要求而且也完全不是面向对象本文建议对 Java 语言进行重大修改和补充以解决这些问题 Java 语言线程模型是此语言个最难另人满意部分尽管 Java 语言本身就支持线程编程是件好事但是它对线程语法和类包支持太少只能适用于极小型应用环境 有关 Java 线程编程大多数书籍都长篇累牍地指出了 Java 线程模型缺陷并提供了解决这些问题急救包(Band-Aid/邦迪创可贴)类库我称这些类为急救包它们所能解决问题本应是由 Java 语言本身语法所包含从长远来看以语法而不是类库思路方法将能产生更高效代码这是编译器和 Java 虚拟器 (JVM) 能同优化代码而这些优化对于类库中代码是很难或无法实现 在我Taming Java Threads (请参阅 参考资料 )书中以及本文中我进步建议对 Java 编程语言本身进行些修改以使得它能够真正解决这些线程编程问题本文和我这本书主要区别是我在撰写本文时进行了更多研究, 所以对书中提议加以了提高这些建议只是尝试性 -- 只是我个人对这些问题想法而且实现这些想法需要进行大量工作以及同行们评价但这是毕竟是个开端我有意为解决这些问题成立个专门工作组如果您感兴趣请发 e-mail 到 [email protected] 旦我真正着手进行我就会给您发通知 这里提出建议是非常大胆有些人建议对 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 对象分配在后台处理这些思路方法请参考我书中第 9章基于类思路方法再看以下 file_io 类它使用了在 Taming Java Threads 中所讨论 Active_object 类来实现异步写操作: 所有写请求都用个dispatch 过程被放在 active-object 输入队列中排队在后台处理这些异步信息时出现任何异常 (exception) 都由 Exception_handler 对象处理此 Exception_handler 对象被传送到 File_io_task 构造您要写内容到文件时代码如下: 这种基于类处理思路方法其主要问题是太复杂了 -- 对于个这样简单操作代码太杂了向 Java 语言引入$task 和 $asynchronous 关键字后就可以按下面这样重写以前代码: 注意异步思路方法并没有指定返回值其句柄将被立即返回而不用等到请求操作处理完成后所以此时没有合理返回值对于派生出模型$task 关键字和 样同效: $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 第 8章中我给出了个服务器端 处理作为线程池例子它是有关使用线程池任务个好例子其基本思路是产生个独立对象任务是监控个服务器端 每当个客户机连接到服务器时服务器端对象会从池中抓取个预先创建睡眠线程并把此线程设置为服务于客户端连接 服务器会产出个额外客户服务线程但是当连接关闭时这些额外线程将被删除实现 服务器推荐语法如下: Socket_server对象使用个独立后台线程处理异步 listen 请求它封装 “接受”循环当每个客户端连接时 listen 请求个 Client_handler 通过 handle 来处理请求每个 handle 请求在它们自己线程中执行(这是个 $pooled 任务) 注意每个传送到$pooled $task 异步消息实际上都使用它们自己线程来处理典型情况下由于个 $pooled $task 用于实现个自主操作;所以对于解决和访问状态变量有关潜在同步问题最好解决思路方法是在 $asynchronous 思路方法中使用 this 是指向对象个独有副本这就是说当向个 $pooled $task 发送个异步请求时将执行个 clone 操作并且此思路方法 this 指针会指向此克隆对象线程的间通信可通过对 同步访问实现 改进synchronized 虽然在多数情况下$task 消除了同步操作要求但是不是所有多线程系统都用任务来实现所以还需要改进现有线程模块 synchronized 关键字有下列缺点: 无法指定个超时值 无法中断个正在等待请求锁线程 无法安全地请求多个锁 (多个锁只能以依次序获得) 解决这些问题办法是:扩展synchronized 语法使它支持多个参数和能接受个超时介绍说明(在下面括弧中指定)下面是我希望语法: synchronized(x && y && z) 获得 x、y 和 z 对象 synchronized(x || y || z) 获得 x、y 或 z 对象 synchronized( (x && y ) || z) 对于前面代码些扩展 synchronized(...)[1000] 设置 1 秒超时以获得个锁 synchronized[1000] f{...} 在进入 f 时获得 this 但可有 1 秒超时 TimeoutException是 RuntimeException 派生类它在等待超时后即被抛出 超时是需要但还不足以使代码强壮您还需要具备从外部中止请求锁等待能力所以当向个等待锁线程传送errupt 思路方法后此思路方法应抛出个 SynchronizationException 对象并中断等待线程这个异常应是 RuntimeException 个派生类这样不必特别处理它 对synchronized 语法这些推荐更改思路方法主要问题是它们需要在 2进制代码级上修改而目前这些代码使用进入监控(enter-monitor)和退出监控(exit-monitor)指令来实现 synchronized 而这些指令没有参数所以需要扩展 2进制代码定义以支持多个锁定请求但是这种修改不会比在 Java 2 中修改 Java 虚拟机更轻松但它是向下兼容现存 Java 代码个可解决问题是最常见死锁情况在这种情况下两个线程都在等待对方完成某个操作设想下面个例子(假设): 设想个线程a 但在获得  lock1 的后在获得 lock2 的前被剥夺运行权 第 2个线程进入运行 b 获得了 lock2 但是由于第个线程占用 lock1 所以它无法获得 lock1 所以它随后处于等待状态此时第个线程被唤醒它试图获得 lock2 但是由于被第 2个线程占据所以无法获得此时出现死锁下面 synchronize-on-multiple-objects 语法可解决这个问题: 编译器(或虚拟机)会重新排列请求锁顺序使lock1 总是被首先获得这就消除了死锁 但是这种思路方法对多线程不定总成功所以得提供些思路方法来自动打破死锁个简单办法就是在等待第 2个锁时常释放已获得这就是说应采取如下等待方式而不是永远等待: 如果等待锁每个使用区别超时值就可打破死锁而其中个线程就可运行我建议用以下语法来取代前面代码: synchronized语句将永远等待但是它时常会放弃已获得锁以打破潜在死锁可能在理想情况下每个重复等待超时值比前个相差随机值 改进wait 和 noty wait/ noty 系统也有些问题: 无法检测 wait 是正常返回还是因超时返回 无法使用传统条件变量来实现处于个“信号”(signaled)状态 太容易发生嵌套监控(monitor)锁定 超时检测问题可以通过重新定义wait 使它返回个 boolean 变量 (而不是 void ) 来解决个 true 返回值指示个正常返回而 false 指示因超时返回 基于状态条件变量概念是很重要如果此变量被设置成false 状态那么等待线程将要被阻断直到此变量进入 true 状态;任何等待 true 条件变量等待线程会被自动释放 (在这种情况下 wait 不会发生阻断)通过如下扩展 noty 语法可以支持这个功能: 嵌套监控锁定问题非常麻烦我并没有简单解决办法嵌套监控锁定是种死锁形式当某个锁占有线程在挂起其自身的前不释放锁时会发生这种嵌套监控封锁下面是此问题个例子(还是假设)但是实际例子是非常多: 此例中在get 和 put 操作中涉及两个锁:个在 Stack 对象上个在 LinkedList 对象上下面我们考虑当个线程试图个空栈 pop 操作时情况此线程获得这两个锁然后 wait 释放 Stack 对象上 但是没有释放在 list 上如果此时第 2个线程试图向堆栈中压入个对象它会在 synchronized(list) 语句上永远挂起而且永远不会被允许压入个对象由于第个线程等待个非空栈这样就会发生死锁这就是说个线程永远无法从 wait 返回由于它占据着锁而导致第 2个线程永远无法运行到 noty 语句 在这个例子中有很多明显办法来解决问题:例如对任何思路方法都使用同步但是在真实世界中解决思路方法通常不是这么简单 个可行思路方法是在wait 中按照反顺序释放当前线程获取 所有 锁然后当等待条件满足后重新按原始获取顺序取得它们但是我能想象出利用这种方式代码对于人们来说简直无法理解所以我认为它不是个真正可行思路方法如果您有好思路方法请给我发 e-mail 我也希望能等到下述复杂条件被实现例如: 其中a 、 b 和 c 是任意对象 修改Thread 类 同时支持抢占式和协作式线程能力在某些服务器应用中是基本要求尤其是在想使系统达到最高性能情况下我认为 Java 编程语言在简化线程模型上走得太远了并且 Java 编程语言应支持 Posix/Solaris “绿色(green)线程”和“轻便(lightweight)进程”概念(在“(Taming Java Threads ”第章中讨论) 这就是说有些 Java 虚拟机实现(例如在 NT 上 Java 虚拟机)应在其内部仿真协作式进程其它 Java 虚拟机应仿真抢占式线程而且向 Java 虚拟机加入这些扩展是很容易 个 Java Thread 应始终是抢占式这就是说个 Java 编程语言线程应像 Solaris 轻便进程样工作 Runnable 接口可以用于定义个 Solaris 式“绿色线程”此线程必需能把控制权转给运行在相同轻便进程中其它绿色线程 例如目前语法: 能有效地为Runnable 对象产生个绿色线程并把它绑定到由 Thread 对象代表轻便进程中这种实现对于现有代码是透明有效性和现有完全 把Runnable 对象想成为绿色线程使用这种思路方法只需向 Thread 构造传递几个 Runnable 对象就可以扩展 Java 编程语言现有语法以支持在个单轻便线程有多个绿色线程(绿色线程的间可以相互协作但是它们可被运行在其它轻便进程 ( Thread 对象) 上绿色进程( Runnable 对象) 抢占)例如下面代码会为每个 runnable 对象创建个绿色线程这些绿色线程会共享由 Thread 对象代表轻便进程 现有覆盖(override)Thread 对象并实现 run 习惯继续有效但是它应映射到个被绑定到轻便进程绿色线程(在 Thread 类中缺省 run 思路方法会在内部有效地创建第 2个 Runnable 对象) 线程间协作 应在语言中加入更多功能以支持线程间相互通信目前PipedInputStream 和 PipedOutputStream 类可用于这个目但是对于大多数应用它们太弱了我建议向 Thread 类加入下列: 增加个 wait_for_start 思路方法它通常处于阻塞状态直到个线程 run 思路方法启动(如果等待线程在 run 的前被释放这没有什么问题)用这种思路方法个线程可以创建个或多个辅助线程并保证在创建线程继续执行操作的前这些辅助线程会处于运行状态 (向 Object 类)增加 $send (Object o) 和 Object=$receive 思路方法它们将使用个内部阻断队列在线程的间传送对象阻断队列应作为第个 $send 副产品被自动创建 $send 会把对象加入队列 $receive 通常处于阻塞状态直到有个对象被加入队列然后它返回此对象这种思路方法中变量应支持设定入队和出队操作超时能力: $send (Object o, long timeout) 和 $receive (long timeout) 对于读写锁内部支持 读写锁概念应内置到 Java 编程语言中读写器锁在“Taming Java Threads ”(和其它地方)中有详细讨论概括地说:个读写锁支持多个线程同时访问个对象但是在同时刻只有个线程可以修改此对象并且在访问进行时不能修改读写锁语法可以借用 synchronized 关键字: 对于个对象应该只有在$writing 块中没有线程时才支持多个线程进入 $reading 块在进行读操作时个试图进入 $writing 块线程会被阻断直到读线程退出 $reading 块 当有其它线程处于 $writing 块时试图进入 $reading 或 $writing 块线程会被阻断直到此写线程退出 $writing 块 如果读和写线程都在等待缺省情况下读线程会首先进行但是可以使用$writer_priority 属性修改类定义来改变这种缺省方式如: 访问部分创建对象应是非法 当前情况下JLS 允许访问部分创建对象例如个构造中创建线程可以访问正被创建对象既使此对象没有完全被创建下面代码结果无法确定: 设置x 为 -1 线程可以和设置 x 为 0 线程同时进行所以此时 x 值无法预测 对此问题个解决思路方法是在构造没有返回的前对于在此构造中创建线程既使它优先级比 线程高也要禁止运行它 run 思路方法 这就是说在构造返回的前start 请求必须被推迟 另外Java 编程语言应可允许构造同步换句话说下面代码(在当前情况下是非法)会象预期那样工作: 我认为第种思路方法比第 2种更简洁但实现起来更为困难 volatile关键字应象预期那样工作 JLS 要求保留对于 volatile 操作请求大多数 Java 虚拟机都简单地忽略了这部分内容这是不应该在多处理器情况下许多主机都出现了这种问题但是它本应由 JLS 加以解决如果您对这方面感兴趣马里兰大学 Bill Pugh 正在致力于这项工作(请参阅参考资料 ) 访问问题 如果缺少良好访问控制会使线程编程非常困难大多数情况下如果能保证线程只从同步子系统中不必考虑线程安全(threadsafe)问题我建议对 Java 编程语言访问权限概念做如下限制;应精确使用 package 关键字来限制包访问权我认为当缺省行为存在是任何种计算机语言个瑕疵我对现在存在这种缺省权限感到很迷惑(而且这种缺省是“包(package)”级别而不是“私有(private)”)在其它方面Java 编程语言都不提供等同缺省关键字虽然使用显式 package 限定词会破坏现有代码但是它将使代码可读性更强并能消除整个类潜在 (例如如果访问权是由于被忽略而不是被故意忽略) 重新引入 private protected 功能应和现在 protected 但是不应允许包级别访问 允许 private private 语法指定“实现访问”对于所有外部对象是私有甚至是当前对象是个类对于“.”左边引用(隐式或显式)应是 this 扩展 public 语法以授权它可制定特定类访问例如下面代码应允许 Fred 类对象可 some_method 但是对其它类对象这个思路方法应是私有 这种建议区别于 C "friend" 机制 在 "friend" 机制中它授权个类访问另个类所有 私有部分在这里我建议对有限思路方法集合进行严格控制访问用这种思路方法个类可以为另个类定义个接口而这个接口对系统其余类是不可见个明显变化是: 除非域引用是真正不变(immutable)对象或 final 基本类型否则所有域定义应是 private 对于个类中域直接访问违反了 OO 设计两个基本规则:抽象和封装从线程观点来看允许直接访问域只使对它进行非同步访问更容易 增加$property 关键字带有此关键字对象可被个“bean 盒”应用访问这个使用在 Class 类中定义反射操作(rospection) API否则和 private private 同效 $property 属性可用在域和思路方法这样现有 JavaBean getter/ter 思路方法可以很容易地被定义为属性 不变性(immutability) 由于对不变对象访问不需要同步所以在多线程条件下不变概念(个对象值在创建后不可更改)是无价Java 编程言语中对于不变性实现不够严格有两个原因:对于个不变对象在其被未完全创建的前可以对它进行访问这种访问对于某些域可以产生不正确 对于恒定 (类所有域都是 final) 定义太松散对于由 final 引用指定对象虽然引用本身不能改变但是对象本身可以改变状态个问题可以解决不允许线程在构造中开始执行 (或者在构造返回的前不能执行开始请求) 对于第 2个问题通过限定final 修饰符指向恒定对象可以解决此问题这就是说对于个对象只有所有域是 final并且所有引用对象域也都是 final此对象才真正是恒定为了不打破现有代码这个定义可以使用编译器加强即只有个类被显式标为不变时此类才是不变类思路方法如下: 有了$immutable 修饰符后在域定义中 final 修饰符是可选 最后当使用内部类(inner )后在 Java 编译器中使它无法可靠地创建不变对象个类有重要内部类时(我代码常有)编译器经常不正确地显示下列信息: 既使空 final 在每个构造中都有还是会出现这个信息自从在 1.1 版本中引入内部类后编译器中直有这个在此版本中( 3年以后)这个依然存在现在该是改正这个时候了 对于类级域例子级访问 除了访问权限外还有个问题即类级(静态)思路方法和例子(非静态)思路方法都能直接访问类级(静态)域这种访问是非常危险例子思路方法同步不会获取类级所以个synchronized 思路方法和个 synchronized 思路方法还是能同时访问类改正此问题个明显思路方法是要求在例子思路方法中只有使用 访问思路方法才能访问非不变类 当然这种要求需要编译器和运行时间检查在这种规定下下面代码是非法: 由于f 和 g 可以并行运行所以它们能同时改变 x 值(产生不定结果)请记住这里有两个锁: 思路方法要求属于 Class 对象而非静态思路方法要求属于此类例子当从例子思路方法中访问非不变 域时编译器应要求满足下面两个结构中任意个: 或则编译器应获得读/写锁使用: 另外种思路方法是(这也是种理想 思路方法)-- 编译器应 自动 使用个读/写锁来同步访问非不变 这样员就不必担心这个问题 后台线程突然结束 当所有非后台线程终止后后台线程都被突然结束当后台线程创建了些全局资源(例如个数据库连接或个临时文件)而后台线程结束时这些资源没有被关闭或删除就会导致问题 对于这个问题我建议制定规则使 Java 虚拟机在下列情况下不关闭应用:有任何非后台线程正在运行或者: 有任何后台线程正在执行个 synchronized 思路方法或 synchronized 代码块 后台线程在它执行完synchronized 块或 synchronized 思路方法后可被立即关闭 重新引入stop 、 suspend 和 resume 关键字 由于实用原因这也许不可行但是我希望不要废除stop (在 Thread 和 ThreadGroup 中)但是我会改变 stop 语义使得它时不会破坏已有代码但是有关 stop 问题请记住当线程终止后 stop 将释放所有锁这样可能潜在地使正在此对象上工作线程进入种不稳定(局部修改)状态由于停止线程已释放它在此对象上所有锁所以这些对象无法再被访问 对于这个问题可以重新定义stop 行为使线程只有在不占有任何锁时才立即终止如果它占据着锁我建议在此线程释放最后个锁后才终止它可以使用个和抛出异常相似机制来实现此行为被停止线程应设置个标志并且当退出所有同步块时立即测试此标志如果设置了此标志就抛出个隐式异常但是此异常应不再能被捕捉并且当线程结束时不会产生任何输出注意微软 NT 操作系统不能很好地处理个外部指示突然停止(abrupt)(它不把 stop 消息通知动态连接库所以可能导致系统级资源漏洞)这就是我建议使用类似异常思路方法简单地导致 run 返回原因 和这种和异常类似处理思路方法带来实际问题是你必需在每个synchronized 块后都插入代码来测试“stopped”标志并且这种附加代码会降低系统性能并增加代码长度我想到另外个办法是使 stop 实现个“延迟(lazy)”停止在这种情况下在下次 wait 或 yield 时才终止我还想向 Thread 中加入个 isStopped 和 stopped 思路方法(此时 Thread 将像 isInterruptederrupted 样工作但是会检测 “stop-requested”状态)这种思路方法不向第种那样通用但是可行并且不会产生过载 应把suspend 和 resume 思路方法放回到 Java 编程语言中它们是很有用我不想被当成是幼儿园小孩由于它们可能产生潜在危险(当被挂起时个线程可以占据个锁)而去掉它们是没有道理请让我自己来决定是否使用它们如果接收线程正占据着锁Sun 公司应该把它们作为 suspend 个运行时间异常处理(run-time exception);或者更好思路方法是延迟实际挂起过程直到线程释放所有 被阻断 I/O 应正确工作 应该能打断任何被阻断操作而不是只让它们wait 和 sleep 我在“ Taming Java Threads ”第 2章中 部分讨论了此问题但是现在对于个被阻断 I/O 操作打断它办法是关闭这个 而没有办法打断个被阻断文件 I/O 操作例如旦开始个读请求并且进入阻断状态后除非到它实际读出些东西否则线程直出于阻断状态既使关掉文件句柄也不能打断读操作 还有应支持 I/O 操作超时所有可能出现阻断操作对象(例如 InputStream 对象)也都应支持这种思路方法: 这和 Socket 类SoTimeout(time) 思路方法是等价同样地应该支持把超时作为参数传递到阻断 ThreadGroup类 ThreadGroup应该实现 Thread 中能够改变线程状态所有思路方法我特别想让它实现 join 思路方法这样我就可等待组中所有线程终止 整理总结 以上是我建议就像我在标题中所说那样如果我是国王...(哎)我希望这些改变(或其它等同思路方法)最终能被引入 Java 语言中我确实认为 Java 语言是种伟大编程语言;但是我也认为 Java 线程模型设计得还不够完善这是件很可惜事情但是Java 编程语言正在演变所以还有可提高前景 参考资料本文是对 Taming Java Threads 更新摘编该书探讨了在 Java 语言中多线程编程陷阱和问题并提供了个和线程相关 Java 包来解决这些问题 马里兰大学 Bill Pugh 正在致力修改 JLS 来提高其线程模型Bill 提议并不如本文所推荐那么广他主要致力于让现有线程模型以更为合理方式运行更多信息可从 www.cs.umd.edu/~pugh/java/memoryModel/ 获得 从 Sun 网站WebSite 可找到全部 Java 语言规范标准 要从个纯技术角度来审视线程参阅 Doug Lea 编著 Concurrent Programming in Java: Design Principles and Patterns 第 2版 这是本很棒但是它风格是非常学术化并不定适合所有读者 Taming Java Threads 是个很好补充读物 由 Scott Oaks 和 Henry Wong 编写 Java Threads 比 Taming Java Threads 要轻量些但是如果您从未编写过线程这本书更为适合Oaks 和 Wong 同样实现了 Holub 提供帮助类而且看看对同问题区别解决方案总是有益 由 Bill Lewis 和 Daniel J. Berg 编写 Threads Primer: A Guide to Multithreaded Programming 是对线程(不限于 Java)很好入门介绍 Java 线程些技术信息可在 Sun 网站WebSite 上找到 在 "Multiprocessor Safety and Java" 中 Paul Jakubik 讨论了多线程系统 SMP 问题
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: