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