??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结果可能不是您所预期的。这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>
Ҏ限制: 1.Ҏ内部限制:采用局部变量方?/p>
2.Ҏ间传递限Ӟ 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.最单的Ҏ是将所有可变对象都攑֜一个线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Ҏ?/p>
在不同步时check一ơ,再在同步状态在check一ơ。这么做的意义在于羃锁使用范围Q在W一ơcheck不满的情况Q蟩出方法,那么锁也q不到了?/p>
c.只对l护状态部分加锁:当对象的某个同步Ҏ是比较耗时的操作,那么锁持有的旉p长,而仅仅是Z保持一个状态是Q可以采用openCall的方式,减少持有锁时间?/p>
public sychronized void updateState(){} public void readFile(){ updateState();//持有?/p>
file.read(); } 如上Q这U方式的前提是程序不需要同步一个方法中无状态的部分。如果整个方法都需要锁Q那q种方式׃适用? D.能用同步块Q就不需同步整个Ҏ?/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{属性都需要同步处理,以保证ƈ发修ҎQ可以设计一些同步的int,Double{类型(util.concurrent已提供类似的c)Q将锁交l辅助类d理。v到隔M? 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的不同Ҏ之间传递对象的引用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.保证同步Ҏ或块的顺序执?/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; } 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>
说明性的安全性:通过安全l构描述的方式来代表应用E序的安全需求,安全l构一般包括安全角Ԍ讉K控制和验证要求等。在j2eeq_中部|描q符?
当了说明的安全性的主要工具。部|描q符是组件开发者和应用E序部v者或应用E序l装者之间的交流工具。应用程序的开发者用它来表示应用中的安全需求,应用E序部v者或应用E序l装者将安全角色与部|环境中的用户和l映v来?/p>
在程序运行时容器从部|描q符中提取出相应的安全策略,然后容器Ҏ安全{略执行安全验证。说明的安全性不需要开发h员编写Q何安全相关的代码Q一切都是通过配置部v描述W来完成的?/p>
可编E的安全? 可编E的安全性在说明性的安全性的基础上,使安全敏感的应用可以通过调用被容器提供的API来对安全作出x。这在说明性的安全性不以满企业的安全模型的情况是非常有用的。比如J2ee在servlet HttpServletRequest interface中各提供两个ҎQ?br />
isUserInRole (HttpServletRequest)——判断用戯?br />
getUserPrincipal (HttpServletRequest) ——获得用戯证信息principal
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:
2.drawString 部分代码
int width, int height, String price, Font font_money, Font font,
Graphics2D g2d, Rectangle2D bounds, Rectangle2D bounds_money) {
BufferedImage image;
//透明背景
image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
g2d.dispose();
g2d = image.createGraphics();
//反锯齿字?br /> g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if(!isWhite){
//非白?br /> g2d.setColor(new Color(236,0,137));
}else{
//白字
g2d.setColor(new Color(255,255,255));
}
//字体居中
double y = (height - bounds.getHeight()) / 2;
double ascent = -bounds.getY();
double baseY = y + ascent;
g2d.setStroke(new BasicStroke(1));
g2d.setFont(font_money);
g2d.drawString(FONT_RMB_CHAR, -2, (int)baseY);
g2d.setFont(font);
g2d.drawString(price, (int)bounds_money.getWidth()-4, (int)baseY);
g2d.dispose();
return image;
}
width = (int)(bounds.getWidth();
4.扚w生成,使用java自带的线E池Qƈ使用CompletionServiceQ目的是在线E处理结束后得到生成成功的ProductId
boolean flag=true;
ExecutorService exec = Executors.newFixedThreadPool(8);
CompletionService<CallBack> completionService=
new ExecutorCompletionService<CallBack>(exec);
long startTime=System.currentTimeMillis();
String sql="select productId,price from prod";
List<Map> skuList = this.cmsJdbcTemplate.queryForList(sql);
for(Map map:skuList){
String prodId=((BigDecimal)map.get("productId")).toString();
double price=((BigDecimal)map.get("price")).doubleValue();
completionService.submit(new CreateImageConcurrent(prodId,price,FontEnum.ONE,false));
completionService.submit(new CreateImageConcurrent(prodId,price,FontEnum.TWO,false)); }
long endTime=System.currentTimeMillis()-startTime;
log.info("query db time>>>>>>>>>>>>>>"+endTime/1000);
Future<CallBack> future;
int count=skuList.size()*6;
log.info("generateImagesBatch count:"+count);
try {
while(count>0){
future = completionService.take();
CallBack callBack = future.get();
if(null!=callBack){
count--; log.info("generateImagesBatch prod id:"+callBack.getSuccesMessage()); }
}
endTime=System.currentTimeMillis()-startTime;
log.info("create images time>>>>>>>>>>>>>>"+endTime/1000);
log.info("generateImagesBatch success!");
flag=true;
} catch (ExecutionException e) {
flag=false;
log.error("generateImagesBatch fail::ExecutionException::"+e.getMessage());
} catch (InterruptedException e) {
flag=false;
log.error("generateImagesBatch fail::InterruptedException::"+e.getMessage());
}finally{
exec.shutdown();
}
return flag;
}
]]>
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操作
Ҏ英文直译其实可以理解其含义,compare and set.
在单U程环境下,d操作都在一个线E内完成Q不存在可见性问题。但是,当读与写操作不在同一个线E内Ӟ需要有可见性的要求——即可变的共享变量对所有线E都是可见的?br />
]]>
下面介绍几个HelloworldCZ:
主要使用了btrace命o:btrace [pid] class
pid可由jps命o快速查?br />
1.监控Ҏ输入参数:
@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.监控Ҏ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.监控Ҏ执行旉
@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!
]]>
]]>
public void doWork() {
while (!shutdownFlag) {
// do something
}
]]>
另外Q就是用戯定义d认证Q而不是用J2EE的部|描q符里面的定?三种d认证cd)?br />
提到安全性,׃能不说到两个概念Q认证与授权?/span>
认证是用h计算讑֤用来验证w䆾的过E。授权是Ҏh用户的n份允许访问和操作一D|感Y件的q程?
q两个概念密不可分。没有授权,
无需知道用户的n份。没能认证,׃可能区分可信和不可信用户Q?
更不可能安全地授权访问许多系l部分?/font>
因ؓ之前的项?00% web方式Q所以本文只讨论web应用的认证和授权?/span>
A.认证方式Q?/strong>
Web客户端通常通过http协议来请求web服务器端的资源,q些web资源通常包括html|页、jspQjava server
pageQ文件、java
servlet和其他一些二q制或多媒体文g。在企业环境中,企业的某些资源往往要求只允许某些h讉KQ有些资源甚x机密的或安全敏感的。因此对企业?
各种web资源q行讉K控制是十分必要的。ؓ了满企业中的不同安全别和客户化的需求,J2EE提供了三U基于web客户端的认证方式Q?br />
HTTP基本验证
是HTTP协议所支持的验证机制。这U验证机制用用L用户名和密码作ؓ验证信息。Web客户端从用户获取用户名和密码Q然后传递他们给web服务
器,web服务器在指定的区域(realmQ中验证用户。但需要注意的是,q种验证Ҏ是不够安全的。因U验证方法ƈ不对用户密码q行加密Q而只是对密码q行基本的base64的编码。而且目标web服务器对用户来说也是非验证过的。不能保证用戯问到的web服务器就是用户希望访问的?/p>
Z表单的验?
使系l开发者可以自定义用户的登陆页面和报错面。这U验证方法与基本HTTP的验证方法的唯一区别在于它可以Ҏ用户的要求制定登陆和出错面。基?
表单的验证方法同样具有与基本HTTP验证cM的不安全的弱炏V用户在表单中填写用户名和密码,而后密码以明文Ş式在|\中传递,如果在网路的某一节点?
此验证请求截P在经q反~码很容易就可以获取用户的密码。因此在使用基本HTTP的验证方式和Z表单的验证方法时Q一定确定这两种方式的弱点对你的?
用是可接受的?
Z客户端证书的验证方式要比上面两种方式更安全。它通过HTTPSQHTTP over SSLQ来保证验证的安全性。安全套接层QSecure
Sockets
LayerQؓ验证q程提供了数据加密,服务器端认证Q信息真实性等斚w的安全保证。在此验证方式中Q客L必须提供一个公钥证书,你可以把q个公钥证书
看作是你的数字护照。公钥证书也U数字证书,它是被称作证书授权机构(CAQ-一个被信Q的组l颁发的。这个数字证书必ȝ合X509公钥体系l构
QPKIQ的标准。如果你指定了这U验证方式,Web服务器将使用客户端提供的数字证书来验证用Lw䆾?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> //受约束的资源操作Ҏ
<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应用
]]>
Executor接口提供一U将d提交与每个Q务将如何q行的机Ӟ包括U程使用的细节、调度等Q分d来的Ҏ?br />
它只有一个方法excute(Runnable command),你可以复写此ҎQ让Runnable同步或异步执?br />
ExecutorService?strong>Executor的一个子接口Q提供了理U程的方法,可ؓ跟踪一个或多个异步d执行状况而生?Future 的方法?br />
ThreadPoolExecutor是ExecutorService的一个实现类Q它通常与Executors工厂一起用?br />
下面的方法取自Executorsc?br />
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
q里面用ThreadPoolExecutor创徏一个线E数为nThreads的线E池?br />
cM的工厂方法还有很多,可以查看JDK
ExecutorService的常用方法:
invokeAll 执行所有Q?全部执行完毕后返回每个Q务的l果(FutureList),包括每个d的状?br />
invokeAny 与上面方法的区别是,只返回一个Q务成功执行结果Future
submit 提交一个TaskL行,q返回执行结?br />
awaitTermination 当执行线E中断、超Ӟ或调用了shutdownҎ后,d直到所有的Task都执行结束?br />
shutdown 关闭所有执行过的Task,q不再接收新U程
isTerminated 如果所有Task都关闭则q回True,前提是调用过shutdown或shutdownNow
2.使用CZQ?/strong>
a.首先定义一个辅助类SystemConstantQ大致方法如下:
//初始化一个线E池
public static ExecutorService getExecutor() {
if(PROCESS_EXECUTOR == null || PROCESS_EXECUTOR.isTerminated()) {
PROCESS_EXECUTOR = Executors.newFixedThreadPool(EXECUTOR_SIZE);
}
return PV_PROCESS_EXECUTOR;
}
//定义关闭Ҏ
public static void awaitTerminationExecutor(long timeout, TimeUnit unit) {
getExecutor().shutdown();
try {
getExecutor().awaitTermination(timeout, unit);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
b.接下来是调用Q?br />
try {
SystemConstant.getExecutor().invokeAll(SystemUtils.toCallable(
new SystemUtils.CallableHandle<IPvProcess>() {
public void handle(Process process) throws Exception {
process.processLogs(logs, statDate);
}
}, prepareProcesses), perOutOfTime, TimeUnit.HOURS);
} catch (Exception e) {
logger.error(e);
}
SystemConstant.awaitTerminationProgramExecutor(allOutOfTime, TimeUnit.HOURS);
3. cȝ构图
java.util.concurrent
Class ThreadPoolExecutor
java.lang.Object
java.util.concurrent.AbstractExecutorService
java.util.concurrent.ThreadPoolExecutor
如果用过pythonQ就知道它有了command line 工具Q比如你输入 print 'a' ,该工兯?aQ好处是便于快速学习python 语法?/p>
其实java也可以做到?/p>
下面是一个java 脚本解释器的helloword版本,思\如下Q?/p>
1动态创Z个Temp.javacLӞ里面只有一个excuteҎQ把从控制台输入 的字W串加入到类Ҏ中,比如for(int i=0;i<10;i++){System.out.println(i);}?/p>
2再利用com.sun.tools.javac.Main.compile 动态编译Temp.java 生成class
3Temp.class载入到jvm
4生成object实例Q利用反执行excuteҎ
说明Q这只是个test版本?/p>
public class Test {
public static void main(String[] args)
throws IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException, IllegalArgumentException, SecurityException,
InvocationTargetException, NoSuchMethodException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true){
String js=reader.readLine();
OutputStream os = new FileOutputStream("Temp.java");
String tempJava="public class Temp"+
" { "+
" public void excute() "+
" { "+
js+
" } "+
" } ";
os.write(tempJava.getBytes());
os.close();
String[] compileArgs = new String[] {"Temp.java"};
com.sun.tools.javac.Main.compile(compileArgs);
URLClassLoader loader =
new URLClassLoader(new URL[]{new File(".").toURI().toURL()});
Class<?> scriptClass = loader.loadClass("Temp");
Object obj = scriptClass.newInstance();
obj.getClass().getDeclaredMethod("excute").invoke(obj);
obj=null;
}
}
}