??xml version="1.0" encoding="utf-8" standalone="yes"?>
CAS 操作包含三个操作?—?
内存位置QVQ、预期原|AQ和新?B)。如果内存位|的g预期原值相匚wQ那么处理器会自动将该位|值更Cؓ新倹{否则,处理器不做Q何操作。CAS 认ؓ位置 V 应该包含?AQ如果包含该|则将 B 攑ֈq个位置Q否则,不要更改该位|,只告诉我q个位置现在的值即可通常?CAS 用于同步的方式是从地址 V d?AQ执行多步计来获得新?BQ然后?CAS ?V 的g A 改ؓ B。如?V 处的值尚未同时更改,?CAS 操作成功? 3.ABA问题 因ؓ在更?V 之前QCAS 主要询问“V 的值是否仍?A”Q所以在W一ơ读?V 以及?V 执行 CAS 操作之前Q如果将g A 改ؓ
BQ然后再改回 AQ会使基?CAS 的算法乱。在q种情况下,CAS 操作会成功,但是在一些情况下Q结果可能不是?zhn)所预期的。这c问题称?
ABA 问题?code> 4.原子操作 A与B两个操作。从执行A的线E看Q当其他U程执行BӞ要么B全部执行完成Q要么一炚w不执行。这样A与B互ؓ原子操作。要保证数据状态的一致性,要在单一的原子操作中更新所有相兌的状态?/p>
5.可见?br />
6.重排?/p>
JVM实现中,U程内部l持序化语义。如果程序的最l结果等同于它在严格的顺序化环境下的l果Q那么指令的执行序可能与代码的顺序不一致。这个过E通过叫做指o的重排序。比如Java存储模型允许~译器重排序操作指oQ在寄存器中~存数|q允许CPU重排序,q在处理器的~存中缓存数倹{?br />
当然Q在没有同步的多U程情况下,~译器,处理器,q行时安排操作的执行序可能完全Zh意料?/p>
7.内部?/p>
每个Java对象都可以隐士的扮演一个用于同步的锁的角色。比如synchronized(object){},执行U程q入synchronized?
之前自动获得锁。无论是正确执行或是抛出异常Q最l都会释放该锁。内部锁是一U互斥锁(mutex)——至多只有一个线E可以拥有锁。JDK中有该锁的实
现?/p>
8.锁与内存 锁不仅仅是关于同步与互斥Q也是关于内存可见性的。ؓ了保证所有线E都能访问共享变量的最新|d写的U程必须使用公用的锁q行同步?/p>
9.锁与volatile 加锁可以保证可见性与原子性,volatile只能保证可见性?/p>
10.happen-before法则 Java存储模型有一个happens-before原则Q就是如果动作B要看到动作A的执行结果(无论A/B是否在同一个线E里面执行)Q那么A/B需要满happens-before关系。比如一个对象构造函数的l束happens-before与该对象的finalizer的开?/p>
参?https://www.ibm.com/developerworks/cn/java/j-jtp11234/ http://www.ibm.com/developerworks/cn/java/j-5things5.html http://www.tkk7.com/xylz/archive/2010/07/03/325168.html 《Java q发~程实践?br />
方式主要三类Q方法限制、线E限制和对象内限?/p>
Ҏ(gu)限制: 1.Ҏ(gu)内部限制:采用局部变量方?/p>
2.Ҏ(gu)间传递限Ӟ a.调用者copyQ比如print(p) 可以改ؓprint(new Point(p)); b.接收者copyQPoint p=new Point(p.x,p.y); c.标量参数Qprint(int x,int y);d.print(p.x,p.y); U程限制Q?/strong> 1.最单的Ҏ(gu)是将所有可变对象都攑֜一个线E内执行 public display(){ new Thread(){ public void run(){//do something here} }.start() } 2.U程U有成员变量 最直接的办法是利用现有c?ThreadLocal. 当然你可以利用Thread.currentThread()自己实现一个类似功能的c?但Thread.currentThread有限Ӟ是对特定线E的一cR?/p>
而ThreadLocal则摆׃q样的限制。而且在线E内对ThreadLocalU有变量的读写不需要同步?/p>
对象限制Q?/p>
在前面两U方法都不能做到对对象的限制讉KӞ你就不得不用锁。但同时Q也可以对对象内部及不同部分的访问进行结构上的限制?/p>
1.适配器模?/p>
比如 class Point{ public double x; public double y; public synchronized double getX(){}; //…… } 采用对象限制的设计方式,会将synchronized 锁移除到一个其他对象里Q这样就解脱了Point. like this class SychPoint { private final Point point=new Point(); public synchronized double getX(){point.x} } class Point{ public double x; public double y; public double getX(){}; } 说白了就是采用适配器模式,改变了一下原来类的结构。java.util.Collection framework 里面是使用q种{略l织起集合类的同步?/p>
2.子类?/p>
锁延迟到子cd玎ͼq里不再罗嗦?/p>
?同步设计 使用锁的注意事项 1.有些入口锁在只有数U程讉K的情况下Q可以很好的工作Q开销q不大。但是当q发量变大,竞争加剧Q开销也变大,pȝ的性能会随之下降。大多数U程会把大部分时间浪费在{待上。系l出C延迟Q限制了q发pȝ的优性?/p>
2.使用太多的锁Q会增加pȝ负担Q以及不可料的情况发生,比如死锁?/p>
3.只用一把锁来保护一个功能的多个斚w会导致资源竞争?/p>
4.长时间持有锁Q会带来性能问题和异常处理的复杂?/p>
5.有时候加锁ƈ不一定能保证得到我们惌的结果?/p>
对付以上q些问题Q没有什么最佳策略,大都需要去权衡各个斚w的利弊来q行设计。写多线E的E序Q前期的设计比后期维护更为重要?/p>
初期的设计原则, 1.减少同步 a.用户可以接受陈旧数据Q可以拿掉同步,使用volatile b.用户在得到非法数据时Q只要能得到提示够了,可以使用double-checkҎ(gu)?/p>
在不同步时check一ơ,再在同步状态在check一ơ。这么做的意义在于羃?yu)锁使用范围Q在W一ơcheck不满的情况Q蟩出方法,那么锁也q不到了?/p>
c.只对l护状态部分加锁:当对象的某个同步Ҏ(gu)是比较耗时的操作,那么锁持有的旉p长,而仅仅是Z保持一个状态是Q可以采用openCall的方式,减少持有锁时间?/p>
public sychronized void updateState(){} public void readFile(){ updateState();//持有?/p>
file.read(); } 如上Q这U方式的前提是程序不需要同步一个方法中无状态的部分。如果整个方法都需要锁Q那q种方式׃适用? D.能用同步块Q就不需同步整个Ҏ(gu)?/p>
2.分解同步Q?/p>
分解c?/p>
锁拆分到辅助类?/p>
分解?/p>
如果不愿分解c,可以设计分解?/p>
private static Object lock1 = new Object(); private static Object lock2 = new Object(); synchronize(lock1){} synchronized(lock2){} 在jdk 5.0之后的ƈ发包里,已有可重入锁供用?/p>
隔离成员变量 Person的age,income{属性都需要同步处理,以保证ƈ发修Ҏ(gu)Q可以设计一些同步的int,Double{类型(util.concurrent已提供类似的c)Q将锁交l辅助类d理。v到隔M?
1.Semaphore?a name="N100B4">CountDownLatch
Semaphore 可用于控?/span>特定资源hQ线E?操作Q数?br />
CountDownLatch 在功能上cM?/span>Semaphore。区别是Q?/span>Semaphore允许一ơ一个线E的话,CountDownLatch可以允许多个U程在特定的旉一h行?br />
2.CAS操作
Ҏ(gu)英文直译其实可以理解其含义,compare and set.
在单U程环境下,d操作都在一个线E内完成Q不存在可见性问题。但是,当读与写操作不在同一个线E内Ӟ需要有可见性的要求——即可变的共享变量对所有线E都是可见的?br />
]]>
下面介绍几个HelloworldCZ:
主要使用了btrace命o:btrace [pid] class
pid可由jps命o快速查?br />
1.监控Ҏ(gu)输入参数:
@OnMethod(
clazz="com.btrace.Person",
method="/set.*/"
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
println(pcn);
println(pmn);
printArray(args);
}
执行btract命o
后台输出:
com.btrace.Person
setId
[1, ]……
2.监控Ҏ(gu)q回?br />
@OnMethod(
clazz="com.btrace.Person",
method="/get.*/",
location=@Location(Kind.RETURN)
)
public static void defineclass(@Return String cl) {
println(Strings.strcat("getValue ", cl));
Threads.jstack();
}
执行btract命o
后台输出:
getValue gum
com.btrace.TestThread.main(TestThread.java:23)
3.监控jvm内存使用情况
@OnTimer(4000)
public static void printMem() {
println("Heap:");
println(heapUsage());
println("Non-Heap:");
println(nonHeapUsage());
}
执行btract命o
后台输出:
Heap:
init = 268435456(262144K) used = 26175176(25561K) committed = 251658240(245760K)
max = 492175360(480640K)
Non-Heap:
init = 12746752(12448K) used = 5892104(5754K) committed = 13598720(13280K) max =
100663296(98304K)
4.监控Ҏ(gu)执行旉
@TLS private static long startTime;
@OnMethod(clazz="com.btrace.Person",method="setId")
public static void onCall(){
println("enter this method");
startTime=timeMillis();
}
@OnMethod(clazz="com.btrace.Person",method="setId",location=@Location(Kind.RETURN))
public static void onReturn(){
println("method end!");
println(strcat("Time taken ms",str(timeMillis()-startTime)));
}
后台输出:
enter this method
method end!
Time taken ms0
5.监控Thread start
@OnMethod(
clazz="java.lang.Thread",
method="start"
)
public static void func() {
println("about to start a thread!");
}
后台输出Qabout to start a thread!
]]>
]]>
]]>
JVMpȝ中存在一个主内存(Main Memory)QJava中所有变量都储存在主存中Q对于所有线E都是共享的?/span>每条U程都有自己的工作内?Working Memory)Q工作内存中保存的是d中某些变量的拯Q线E对所有变量的操作都是在工作内存中q行Q线E之间无法相互直接访问,变量传递均需要通过d完成?/span>
模型的规则:
1.原子性:保证E序得到成员变量Q非局部变量)的值或者是初始|又或者是某线E修改后的,l对不是多个U程混ؕ修改后的?/p>
2.可见?׃n内存的数?Q什么情况下Q写入成员变量的值对d该变量的值是可见的?
A.写操作释放了同步锁,L作获得了同步?/p>
原理Q释N的时候强制线E把所使用的工作内存中的值刷新到dQ获得锁的时候从d重新装蝲倹{?/p>
p.s.锁只被同步块和方法中的操作占有,但却控制了执行该操作的线E的所有成员变量?/p>
B.如果一个成员变量ؓvolatile,那么在写U程做存储操作前Q写入这个成员变量的数据会在d中刷斎ͼq对其他U程可见。读U程每次使用q个成员变量前都要重CdL据?/p>
C.如果一个线E访问一个对象的成员变量Q读到的gؓ初始值或者另一个线E修改后的倹{?/p>
p.s. 不要对引用未完全创徏好的对象?/p>
如果一个类可以被子cdQ那么在构造函数里启动一个线E是非常危险?/p>
D.当一个线E结束后Q所有的写入数据都会被刷新到d?/p>
p.s.同一个线E的不同Ҏ(gu)之间传递对象的引用Q永q不会有可见性问?/p>
存储模型保证Q如果上面的操作都会发生Q那么一个线E对一个成员变量的更新最l对另一个线E是可见的?/p>
3.序?内存操作的顺?Q什么情况下Q一个线E的操作可以是无序的Q顺序化的问题主要围l和d有关的赋D句的执行序?/p>
如果采用同步机制Q那不用多说Q顺序化可以保证?/p>
当没有同步机制时Q存储模型所做的保证是难以相信的。在多线E环境下Q存储模型是难以保证一定正的?/p>
只有当满下面的三个原则Q顺序化才得以保证?/p>
A.从线E执行方法的角度看,如果指o都是串行执行的,那么序可以保证
B.保证同步Ҏ(gu)或块的顺序执?/p>
C.使用volatile定义成员变量
U程执行q程中,存储模型与锁的关p?
(1) 获取对象的锁
(2) 清空工作内存数据, 从主存复制变量到当前工作内存, 卛_步数?
(3) 执行代码Q改变共享变量?/span>
(4) 工作内存数据刷回主?/span>
(5) 释放对象的锁
最后介l一下volatile关键?/p>
volatile定义的成员变量可以保证可见性和序化,但不保证原子性。比如count++?br /> *比如把一个变量声明ؓvolatileQƈ不能保证q个变量引用的非volatile数据的可见性。比如volatile string[10]Q数l)
正确使用volatile的前提条?/p>
a.对变量的写操作不依赖于当前?/p>
b.不要和其他成员变量遵守不变约束。见*处的解释
volatile的应?/p>
a.状态标?/p>
volatile boolean shutdownFlag;
public void shutdown() { shutdownFlag= true; }
public void doWork() {
while (!shutdownFlag) {
// do something
}
b.假设一个后台线E可能会每隔几秒d一ơ数据库里的合同金额Qƈ更新?volatile 变量。然后,其他U程可以dq个变量Q从而随时能够看到最新的金额?比较q泛应用在统计类的系l中?/p>
参考文?
http://www.cs.umd.edu/~pugh/java/memoryModel/
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
《Javaq发~程Q设计原则与模式?/p>
1.q代问题
多线E环境下QP代容易引起问题,?/p>
for(int i=0;i<v.size();i++){System.out.println(v.get(i))}
解决办法之一Q?/p>
客户端加?/p>
for(int i=0;true;i++){
Sychronzied(v){
if(i<v.size()){
System.out.println(v.get(i)
}
}
}Q当然这U也有问题,一旦程序可以重新设|元素位|,也会出错?/p>
q好有一U比较安全的办法Q?copy遍历对象
Sychronzied(v){
Object v_clone= copy(v);
}
iterateV(v_clone);
2.Singleton
单例习惯的方式,采用延时初始化,
public static A getInstance(){
if(null==instance){
instance=new A();
}
return instance
}
在多U程模式下,需要加锁,来保证同步Sychronized(object){}?/p>
如果初始化对象ƈ不占用太多资源,其实没有必要加锁Q毕竟同步也是很耗资源的。取消g时初始化Qpriavte static final instance=new A();
3.序化资?/p>
序化资源是避免死锁的简单的方式?/p>
死锁:T1旉Q线EA 拥有objA的锁Q请求objB的锁。线EB拥有objB的锁Q请求objA的锁?/p>
如: System.identityHashCode(objA)<System.identityHashCode(objB)
或者:public sychronized add(A a){sychronized(a){//do something}}
4.wait and notify
race conditionQobjA在被wait之前已经被另一U程objB lnotify ? 之后的wait 会永久停?q导致deadlock(死锁)Q当Ӟ如果你确认可以控制wait-notify很好,׃需要加?/p>
Annotations | Lazy | Fetch |
---|---|---|
@[One|Many]ToOne](fetch=FetchType.LAZY) | @LazyToOne(PROXY) | @Fetch(SELECT) |
@[One|Many]ToOne](fetch=FetchType.EAGER) | @LazyToOne(FALSE) | @Fetch(JOIN) |
@ManyTo[One|Many](fetch=FetchType.LAZY) | @LazyCollection(TRUE) | @Fetch(SELECT) |
@ManyTo[One|Many](fetch=FetchType.EAGER) | @LazyCollection(FALSE) | @Fetch(JOIN) |
~存的注释写法如下,加在Entity的javacMQ?br />
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
~存的方式有四种Q分别ؓQ?/p>
说明性的安全性:通过安全l构描述的方式来代表应用E序的安全需求,安全l构一般包括安全角Ԍ讉K控制和验证要求等。在j2eeq_中部|描q符? 当了说明的安全性的主要工具。部|描q符是组件开发者和应用E序部v者或应用E序l装者之间的交流工具。应用程序的开发者用它来表示应用中的安全需求,应用E序部v者或应用E序l装者将安全角色与部|环境中的用户和l映v来?/p>
在程序运行时容器从部|描q符中提取出相应的安全策略,然后容器Ҏ(gu)安全{略执行安全验证。说明的安全性不需要开发h员编写Q何安全相关的代码Q一切都是通过配置部v描述W来完成的?/p>
可编E的安全? 可编E的安全性在说明性的安全性的基础上,使安全敏感的应用可以通过调用被容器提供的API来对安全作出x。这在说明性的安全性不以满企业的安全模型的情况是非常有用的。比如J2ee在servlet HttpServletRequest interface中各提供两个Ҏ(gu)Q?br />
isUserInRole (HttpServletRequest)——判断用戯?br />
getUserPrincipal (HttpServletRequest) ——获得用戯证信息principal
另外Q就是用戯定义d认证Q而不是用J2EE的部|描q符里面的定?三种d认证cd)?br />
HTTP基本?/strong>证(HTTP Basic AuthenticationQ?/strong>
Z表单?/strong>?/strong>证(Form-Based AuthenticationQ?/strong>
Z客户端证书的?/strong>证(Client-Certificate AuthenticationQ?/strong>
B.授权模型Q?/strong> 代码授权QCode AuthorizationQ?/strong>
调用者授权(Caller AuthorizationQ?/strong> ——这个是我们常用的方?br />
安全角色Q安全角色是h相同安全属性的逻辑l。比如是admin,Supervisor{?/p>
用户和组Q用户和l是在实际系l环境下的用户和用户的集合。它们对应者现实当中的人和体?
讉K控制Q访问控制可以确保安全角色只能访问已授予它安全权限的授权对象。授权对象包括EJB的远E方法、web资源Qhtml|页Qjsp/servlet和多媒体或二q制文gQ等。在j2ee中访问控制在应用E序描述文g中与安全角色兌h?
映射Q通过映射应用E序的系l管理员实际系l环境中的用户与安全角色联系hQ从而是实际的用h有对企业资源讉K的适当授权?nbsp; C.部v描述W安全性相关介l:
HTTP基本验证
是HTTP协议所支持的验证机制。这U验证机制用用L(fng)用户名和密码作ؓ验证信息。Web客户端从用户获取用户名和密码Q然后传递他们给web服务
器,web服务器在指定的区域(realmQ中验证用户。但需要注意的是,q种验证Ҏ(gu)是不够安全的。因U验证方法ƈ不对用户密码q行加密Q而只是对密码q行基本的base64的编码。而且目标web服务器对用户来说也是非验证过的。不能保证用戯问到的web服务器就是用户希望访问的?/p>
Z表单的验?
使系l开发者可以自定义用户的登陆页面和报错面。这U验证方法与基本HTTP的验证方法的唯一区别在于它可以Ҏ(gu)用户的要求制定登陆和出错面。基?
表单的验证方法同样具有与基本HTTP验证cM的不安全的弱炏V用户在表单中填写用户名和密码,而后密码以明文Ş式在|\中传递,如果在网路的某一节点?
此验证请求截P在经q反~码很容易就可以获取用户的密码。因此在使用基本HTTP的验证方式和Z表单的验证方法时Q一定确定这两种方式的弱点对你的?
用是可接受的?
Z客户端证书的验证方式要比上面两种方式更安全。它通过HTTPSQHTTP over SSLQ来保证验证的安全性。安全套接层QSecure
Sockets
LayerQؓ验证q程提供了数据加密,服务器端认证Q信息真实性等斚w的安全保证。在此验证方式中Q客L(fng)必须提供一个公钥证书,你可以把q个公钥证书
看作是你的数字护照。公钥证书也U数字证书,它是被称作证书授权机构(CAQ-一个被信Q的组l颁发的。这个数字证书必ȝ合X509公钥体系l构
QPKIQ的标准。如果你指定了这U验证方式,W(xu)eb服务器将使用客户端提供的数字证书来验证用L(fng)w䆾?nbsp;
j2ee产品通过java 2 安全模型来限制特定J2SE的类和方法的执行Q以保护和确保操作系l的安全?/p>
安全U束——定义那些资源是受约束访问的Q以及认证通过后的授权范围
<security-constraint> //安全U束部分
<web-resource-collection> //受约束的web资源?
<web-resource-name>WRCollection</web-resource-name> //资源集名
<url-pattern>/webtest.jsp</url-pattern> //资源的url表达?
<http-method>GET</http-method> //受约束的资源操作Ҏ(gu)
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint> //对安全角色授?
<role-name>user</role-name> //安全角色?
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
参?http://www.ibm.com/developerworks/cn/java/l-j2eeSecurity/
定义安全角色
<security-role>
<description>this is a user</description>
<role-name>user</role-name>
</security-role>
基本的HTTP认证方式——用不?br />
<login-config> //验证方式讄
<auth-method>BASIC</auth-method> //使用基本的HTTP验证方式
<realm-name></realm-name>
</login-config>
Z表单的认证方式——用较?br />
<login-config>
<auth-method>FORM</auth-method> //使用Z表单的验证方?
<realm-name>Default</realm-name> //使用~省的安全域
<form-login-config>
<form-login-page>/login.html</form-login-page> //定义登陆面
<form-error-page>/error.html</form-error-page> //定义出错面
</form-login-config>
</login-config>
Z证书的认证方式——与CA用户数据中心一起?br />
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
注:后两U均在项目中应用q?br />
以上三种认证方式都属于配|式d认证?br />
q有一U是E序?~程?的登录认证,即通过web application自nq行验证Q比较典型的是利用过滤器代理操作?br />
比如开源的acegiQ用它你将无需再web.xml里配|如此多的东?当然Q也多了许多acegi的配|??br />
企业UJava安全性——构建安全的J2EE应用
]]>
此关键字让规则引擎知道,myGlobalList对象应该可以从规则中讉K.ruleQ定义了一个规?br />常用的属性:
rule "<name>"
<attribute>*
when
<conditional element>*
then
<action>*
end
<name> 即rule的名字标?br />
<attribute>:
lock-on-activeQtrue 可以看作是no-loop的加强版Q当条gl果更改后,不但修改此条件的规则不会重新执行Q文件中的Q何规则(?active-lock 属性被设ؓtrue
Q不会重新执行?/pre>salience
Q?00 使用它可以让规则执行引擎知道应该启动规则的结果语句的序。具有最高显著值的规则的结果语句首先执行;hW二高显著值的规则的结果语句第二执行,依此cL。当(zhn)需要让规则按预定义序启动Ӟq一炚w帔R要?br />
其他属性的解释误http://downloads.jboss.com/drools/docs/5.1.1.34858.FINAL/drools-expert/html_single/index.html#d0e2607
when:填写条g的地方,比如Q?br />Cheese( type == "stilton", price < 10, age == "mature" )?br />then:业务规则的地方,略?br />
Cheese( type == "stilton" && price < 10, age == "mature" )
2.用法
规则文g定义好后Q就该是怎么使用它了
如上图,file rule定义好后Q就该是如何使用它了。最重要的两个类RuleBase和W(xu)orkingMemory
下面是一个example:
public class RulesEngine {
private RuleBase rules;
private boolean debug = false;
public RulesEngine(String rulesFile) throws RulesEngineException {
super();
try {
// Read in the rules source file
Reader source = new InputStreamReader(RulesEngine.class
.getResourceAsStream("../../rules/" + rulesFile));
// Use package builder to build up a rule package
PackageBuilder builder = new PackageBuilder();
// This will parse and compile in one step
builder.addPackageFromDrl(source);
// Get the compiled package
Package pkg = builder.getPackage();
// Add the package to a rulebase (deploy the rule package).
rules = RuleBaseFactory.newRuleBase();
rules.addPackage(pkg);
} catch (Exception e) {
throw new RulesEngineException(
"Could not load/compile rules file: " + rulesFile, e);
}
}
public RulesEngine(String rulesFile, boolean debug)
throws RulesEngineException {
this(rulesFile);
this.debug = debug;
}
public void executeRules(WorkingEnvironmentCallback callback) {
WorkingMemory workingMemory = rules.newStatefulSession();
if (debug) {
workingMemory
.addEventListener(new DebugWorkingMemoryEventListener());
}
callback.initEnvironment(workingMemory);
workingMemory.fireAllRules();
}
}
RulesEngine构造方法演CZ如何去读入一个rule文g,q构Z一个RuleBase对象(RuleBase 是一个包含了rule文g的所有规则的集合)
executeRulesҎ(gu)定义了如何用规则文件中定义的那些内容,用RuleBase构徏一个WorkingMemory对象Q再执行fireAllRules()Ҏ(gu)?br /> WorkingMemory 代表了与rulebase链接的session会话Q也可以看作是工作内存空间。如果你要向内存中插入一个对象可以调用insert()Ҏ(gu),同理Q更C个对象用update()Ҏ(gu)。WorkingMemoryq有一个setGlobal()Ҏ(gu)Q用来设|规则内可以引用的对?相当于规则的全局变量)?br />
3.技?/strong>
可以一ơ把所有的rule文g都蝲入内存中存放Q这样就不用每次执行都读取文件?br /> 如果规则文g被修改,也可以用q一个方法来判断是否需要重新蝲入rule文g
比如Q根据文件的最后修Ҏ(gu)_与内存中对应对象的时间做比较
public boolean hasChange(List<RuleFile> ruleFileList){
for(RuleFile ruleFile:ruleFileList){
if(!ruleFile.getLastModifyTime().equals(ruleFileMap.get(ruleFile.getFileName()).getLastModifyTime())){
return true;
}
}
return false;
}
注:具体的helloWorld 误http://www.ibm.com/developerworks/cn/java/j-drools/#listing12Q比我说得好多了?br />
]]>