禹晓辉 蒋晓冬
摘 要:如何在传统的博奕程序中引入Java多线程机制,以提高博奕树搜索效率,并给出了1个具体的应用实例。 关键词:Java 多线程机制 博奕树
线程是操作系统的一种新概念,是比传统进程粒度更小的可并发执行的单位。C和C++采用单线程体系结构,而Java却提供了多线程支持。一方面,Java环境本身就是多线程的;另一方面,Java语言内置多线程控制,提供了1个类Thread,由它负责启动、运行和终止线程,并可检查线程状态。Java的线程还包括了用于对多线程实行并发控制的同步原语。利用Java的多线程编程接口,可方便地构筑支持多线程的应用,提高程序的并发度和执行效率。 笔者曾参与开发了基于IBM Visual Age for Java环境的黑白棋博奕程序。通过将Java多线程机制引入博奕树搜索,明显加大了搜索平均深度,取得了很好的效果。
1 线程的概念及生命周期
所谓“线程”是“进程”中某个单一顺序的控制流。新兴的操作系统,如Macos、Windows NT等,均把线程视为其基本执行单位。线程也是Java中相当重要的组成部分,如任何1个Java Applet的Paint()和update()方法均由AWT绘图与事件处理线程所调用。图1表示了线程在它的生命周期中的任何时刻所能处的状态以及引起状态改变的方法。
图1 线程生命周期
2 博奕
博奕就是对策或斗智,它不仅存在于棋类游戏中,而且存在于政治、经济、军事和生物竞争之中。在人工智能领域,大多以下棋为例来研究博奕规律。博奕为人工智能提供了1个很好的试验场所,人工智能中的许多概念和方法都是从棋类程序中提炼而得,博奕的许多研究成果现已用于军事指挥和经济决策系统之中。 博奕问题的状态空间――博奕树是1种特殊的与/或树,结点代表格局。所谓格局就是反映下棋态势的全部信息,如棋子位置、轮到谁走下一步等,可用状态变量表示。图2是1棵博奕树的局部。
图2 博奕树局部
在2人零和非偶然性全信息博奕中(即对奕双方利益完全对立),对奕双方都力图在状态空间中找到1条使自己得分最多的路径。设所有使甲方获胜的终局为可解端结点,得分为+b;所有使乙方获胜的终局为不可解端结点,得分为-b;分别按甲方与乙方走法,从端结点向根可一步步推算出各中间结点和根结点的得分,这就是对博奕树的极小极大化分析法。 然而,即使1个很小的博奕状态空间,也可能生成十分庞大的博奕树,它可能有的终局数也很大。企图对它们采用完整的极小极大化分析是不可能的,实际可行的办法是:在1个被分析的结点下面,只生成“似合理的”博奕树的一部分(给定深度限制,除去重复和希望不大的分枝),并用得分函数f对树的各叶结点进行得分估值,然后用极大极小化分析计算树中各结点及根结点的得分估值,以便选择当前估计的最佳策略。这些计算所得的估值称为倒推估值(Back up Value),其精度有赖于得分函数。 显然,如何在限定的时间内(本系统为5s)尽量提高搜索的深度是至关重要的。一般认为这有待硬件设施的提升,然而研究后发现,在传统的单线程博奕程序中,对手用于思考棋步的时间对己方而言是闲置的,而且也很难被利用。但在引入多线程机制后,采用“时间窃取”的技术,将对方的思考时间转变为我方的可利用时间,用于增加搜索深度,或在搜索深度不变条件下,提高得分函数的精度,从而显著改善了博奕程序的整体性能。
3 应用实例
基于上述思想,我们在IBM Visual Age for Java环境下开发了黑白棋博奕程序。下面给出该程序的主体架构及涉及多线程应用的相关代码。为便于理解有必要先将黑白棋规则作一下简要介绍。 1.黑白棋规则 (1)棋盘为8×8方格,双方分别执黑白2色棋子。 (2)初始状态:棋盘中间4格放入黑、白各2棋子,如图3(a)。 (3)投子、吃子规则(以黑子为例): ①当黑棋落子时,以此格为中心分别沿8个方向(上、下、左、右、左上、右上、左下、右下)来寻找原有的黑白子,若在某个方向上找到的第一个黑子与刚投下的黑子间无空格,则这2个黑子间的所有白子变为黑子,如图3(b)、图3(c)。 |