分享
 
 
 

关于解决Java编程语言线程问题的建议

王朝java/jsp·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

Java 编程语言的线程模型可能是此语言中最薄弱的部分。它完全不适合实际复杂程序的要求,而且也完全不是面向对象的。本文建议对 Java 语言进行重大修改和补充,以解决这些问题。

Java 语言的线程模型是此语言的一个最难另人满意的部分。尽管 Java 语言本身就支持线程编程是件好事,但是它对线程的语法和类包的支持太少,只能适用于极小型的应用环境。

关于 Java 线程编程的大多数书籍都长篇累牍地指出了 Java 线程模型的缺陷,并提供了解决这些问题的急救包(Band-Aid/邦迪创可贴)类库。我称这些类为急救包,是因为它们所能解决的问题本应是由Java 语言本身语法所包含的。从长远来看,以语法而不是类库方法,将能产生更高效的代码。这是因为编译器和Java 虚拟器 (JVM) 能一同优化程序代码,而这些优化对于类库中的代码是很难或无法实现的。

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 对象的分配程序在后台处理这些方法。请参考我的书中第九章的基于类方法,再看以下的 file_io 类,它使用了在《Taming Java Threads》中所讨论的 Active_object类来实现异步写操作:

interface Exception_handler

{

void handle_exception( Throwable e );

}

class File_io_task

{

Active_object dispatcher = new Active_object();

final OutputStream

file;

final Exception_handler handler;

File_io_task( String file_name, Exception_handler handler )

throws IOException

{

file = new FileOutputStream( file_name );

this.handler = handler;

}

public void write( final byte[] bytes )

{

// The following call asks the active-object dispatcher

// to enqueue the Runnable object on its request

// queue. A thread associated with the active object

// dequeues the runnable objects and executes them

// one at a time.

dispatcher.dispatch

(

new Runnable()

{

public void run()

{

try

{

byte[] copy new byte[ bytes.length ];

System.arrayCopy(

bytes,

0,

copy,

0,

bytes.length );

file.write( copy );

}

catch( Throwable problem )

{

handler.handle_exception( problem );

}

}

}

);

}

}

所有的写请求都用一个 dispatch() 过程调用被放在 active-object的输入队列中排队。在后台处理这些异步信息时出现的任何异常(exception) 都由 Exception_handler 对象处理,此 Exception_handler对象被传送到 File_io_task 的构造函数中。您要写内容到文件时,代码如下:

File_io_task io =

new File_io_task

( "foo.txt"

new Exception_handler

{

public void handle( Throwable e )

{

e.printStackTrace();

}

}

);

//...

io.write( some_bytes );

这种基于类的处理方法,其主要问题是太复杂了 -- 对于一个这样简单的操作,代码太杂了。向 Java 语言引入 $task 和 $asynchronous 关键字后,就可以按下面这样重写以前的代码:

$task File_io $error{ $.printStackTrace(); }

{

OutputStream file;

File_io( String file_name ) throws IOException

{

file = new FileOutputStream( file_name );

}

asynchronous public write( byte[] bytes )

{

file.write( bytes );

}

}

注意,异步方法并没有指定返回值,因为其句柄将被立即返回,而不用等到请求的操作处理完成后。所以,此时没有合理的返回值。对于派生出的模型, $task 关键字和 class 一样同效:$task 可以实现接口、继承类和继承的其它任务。标有 asynchronous 关键字的方法由$task 在后台处理。其它的方法将同步运行,就像在类中一样。

$task 关键字可以用一个可选的 $error 从句修饰 (如上所示), 它表明对任何无法被异步方法本身捕捉的异常将有一个缺省的处理程序。我使用 $ 来代表被抛出的异常对象。如果没有指定 $error 从句,就将打印出一个合理的出错信息(很可能是堆栈跟踪信息)。

注意,为确保线程安全,异步方法的参数必须是不变 (immutable) 的。运行时系统应通过相关语义来保证这种不变性(简单的复制通常是不够的)。

所有的 task 对象必须支持一些伪信息 (pseudo-message),例如:

some_task.close()

在此调用后发送的任何异步信息都产生一个TaskClosedException。但是,在 active 对象队列上等候的消息仍能被提供。

some_task.join()

调用程序

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有