??xml version="1.0" encoding="utf-8" standalone="yes"?>在线成人av观看,国产精品二区三区四区,久久免费精品日本久久中文字幕http://www.aygfsteel.com/yongboy/category/54839.html记录工作/学习(fn)的点Ҏ(gu)滴?/description>zh-cnMon, 01 Jun 2015 06:30:02 GMTMon, 01 Jun 2015 06:30:02 GMT60哈,又一ƾ超U简单的队列QMQQ实现方案来了~http://www.aygfsteel.com/yongboy/archive/2012/03/20/372308.htmlnieyongnieyongTue, 20 Mar 2012 12:30:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/03/20/372308.htmlhttp://www.aygfsteel.com/yongboy/comments/372308.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/03/20/372308.html#Feedback4http://www.aygfsteel.com/yongboy/comments/commentRss/372308.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/372308.html 开源的消息队列已经很多了,但大部分很重Q实际环境下Q很多可能只是用到了一点功能而已Q杀鸡用牛刀Q着实有些浪费了。很多时候,我们只想要一片绿Ӟ但它们给了我们整个的春天Q很难消化。本着DIR_Q?也琢了一个超U简单的队列实现?/div>
说是񔽎单,嗯,l对是超U简单,队列的存储采用Redisq行持久化存储,采用Netty提供HTTP方式的队列的?入。Redis的客L(fng)采用的Jedis。然后呢Q然后就没了啊?/div>

一。Redis

Redis内置订阅发布模型(Publish/Subscribe),其缺hQ不存储Q一旦订阅者断U,无法接收到消息Q再ơ连接上之后Q在断线期间发布者发布的消息都是无法获取到的。只能采用list数组实现Q采用rpush/lpopl合命o(h)来实现先q先出的队列模型Q当然redis也提供了d版本的blpush/brpush/blpop/brpop{,q我们实际环境下如何用了?/div>
JAVA客户端用JedisQ提供接口也很丰富。但要注意的是,需要用连接池Q否则在大数量的情况下,有可能j(lu)edis的连接不够用?
private static JedisPool pool;
 static {
  ResourceBundle bundle = ResourceBundle.getBundle("redis");
  if (bundle == null) {
   throw new IllegalArgumentException(
     "cannot find the SignVerProp.properties");
  }
  JedisPoolConfig config = new JedisPoolConfig();
  config.setMaxActive(Integer.valueOf(bundle
    .getString("redis.pool.maxActive")));
  config.setMaxIdle(Integer.valueOf(bundle
    .getString("redis.pool.maxIdle")));
  config.setMaxWait(Integer.valueOf(bundle
    .getString("redis.pool.maxWait")));
  pool = new JedisPool(config, bundle.getString("redis.server"),
    Integer.valueOf(bundle.getString("redis.port")));
 }

二。Netty

很成熟的NIO框架Q用它来提供HTTP方式的队列的出入。嗯Q目前只提供HTTP方式的入队列Q出队列{?br />HTTP形式为:(x)http://服务器名U?端口/队列操作原语/队列名称?msg=消息内容
队列操作原语Q只有get和putQget为出队列Qput为入队列?br />q回为jsonQ? {s:0, m:'错误消息/消息内容'}
s为success的羃写,gؓ(f)0Q意味着falseQ?对应成功? m为message的羃写,错误消息/消息内容Q添加消息时Q会(x)q回插入消息对应的数? 默认采用UTF-8?/div>
入队列:(x)http://localhost:8080/put/demo?msg=消息内容
出队列:(x)http://localhost:8080/get/demo HTTP方式Q特别适合局域网之间Q消息数据的推送?/div>

三。入口解?/h3>
采用了QueueDaemon装了netty代码Q? 调用很简单,E序启动的入口:(x) 而HTTP方式队列h处理器ؓ(f)HttpRequestHandlerQ?

四。队列处理器

q个很简单,直接采用Jedis客户端即可,q里一直占用一个连接,不释放?

五。ab压力试

本机配置QPentium(R) Dual-Core CPU E5200 2.50GHzQ?span style="text-indent: 2em;">2.00 GB内存QW(xu)indows XPpȝQredis-2.4.5-win32 32版本Q非linux版本Q,都在一台机器上q行?/span> 插入 512 bytes 文本消息队列: 1781.24 requests/sec
D:\Apache2.2\bin>ab -c 10 -n 100000 "http://localhost:8080/put/demo?msg=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software:
Server Hostname:        localhost
Server Port:            8080
Document Path:          /put/demo?msg=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Document Length:        12 bytes
Concurrency Level:      10
Time taken for tests:   56.141 seconds
Complete requests:      100000
Failed requests:        99991
   (Connect: 0, Receive: 0, Length: 99991, Exceptions: 0)
Write errors:           0
Total transferred:      8188895 bytes
HTML transferred:       1588895 bytes
Requests per second:    1781.24 [#/sec] (mean)
Time per request:       5.614 [ms] (mean)
Time per request:       0.561 [ms] (mean, across all concurrent requests)
Transfer rate:          142.45 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.7      0      16
Processing:     0    5  10.7      0     781
Waiting:        0    5  10.4      0     766
Total:          0    6  10.8      0     781
Percentage of the requests served within a certain time (ms)
  50%      0
  66%     16
  75%     16
  80%     16
  90%     16
  95%     16
  98%     16
  99%     16
 100%    781 (longest request)
插入 512 bytes 文本消息队列(dKeep-Alive支持): 1875.18 requests/sec
D:\Apache2.2\bin>ab -k -c 10 -n 100000 "http://localhost:8080/put/demo?msg=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software:
Server Hostname:        localhost
Server Port:            8080
Document Path:          /put/demo?msg=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Document Length:        17 bytes
Concurrency Level:      10
Time taken for tests:   53.328 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      8300000 bytes
HTML transferred:       1700000 bytes
Requests per second:    1875.18 [#/sec] (mean)
Time per request:       5.333 [ms] (mean)
Time per request:       0.533 [ms] (mean, across all concurrent requests)
Transfer rate:          151.99 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.5      0      16
Processing:     0    5   7.8      0     203
Waiting:        0    5   7.8      0     203
Total:          0    5   7.9      0     203
Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%     16
  80%     16
  90%     16
  95%     16
  98%     16
  99%     16
 100%    203 (longest request)
获取 512 bytes 消息(With Keep-Alive): 1875.73 requests/sec
D:\Apache2.2\bin>ab -k -c 10 -n 100000 "http://localhost:8080/get/demo"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software:
Server Hostname:        localhost
Server Port:            8080
Document Path:          /get/demo
Document Length:        523 bytes
Concurrency Level:      10
Time taken for tests:   53.313 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      58900000 bytes
HTML transferred:       52300000 bytes
Requests per second:    1875.73 [#/sec] (mean)
Time per request:       5.331 [ms] (mean)
Time per request:       0.533 [ms] (mean, across all concurrent requests)
Transfer rate:          1078.91 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.9      0      16
Processing:     0    5   7.5      0      94
Waiting:        0    4   6.9      0      94
Total:          0    5   7.6      0      94
Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%     16
  80%     16
  90%     16
  95%     16
  98%     16
  99%     16
 100%     94 (longest request)

其它问题

  1. 暂时对安?授权没有支持Q这个其实很Ҏ(gu)实现
  2. 队列处理器很单,直接使用jedis卛_
  3. 寚w列数据进行分?sharding)Q写一个QueueService实现卛_
  4. 对Redis的内存持久化不放心,采用diskstore存储模式好了Q在Redis中配|,不涉?qing)到E序
  5. 寚w列分布式存储Q写一个QueueService实现Q其它可不用变化
  6. 不适合严格意义上的订阅/发布模型Q这里适合多个发布?单个订阅者环?/li>
  7. HTTPhq回内容为json格式Qxml格式Q暂时不需?/li>
  8. 局域网环境下,pȝ之间q行消息的推?通知Q?/li>
目下蝲地址Q?a target="_blank">http://code.google.com/p/nettyqueue/ 参考资料:(x)
  1. httpsqs


nieyong 2012-03-20 20:30 发表评论
]]>Fork/Join模式(JSR166y)手记之Fork/Join模式实现析1http://www.aygfsteel.com/yongboy/archive/2012/02/08/370142.htmlnieyongnieyongWed, 08 Feb 2012 13:35:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/02/08/370142.htmlhttp://www.aygfsteel.com/yongboy/comments/370142.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/02/08/370142.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/370142.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/370142.html对Fork/Join的个人理解要点:(x)
  • fork/join大的Q务分割小的Q务,直到的d可以使用最单、直接或者同步的方式处理?/li>
  • 最的d无法分?/li>
  • 每一个Q务不是线E的实例
  • 每一个工作线E将是一个隐式的U程实例
  • 每一个工作线E都?x)维护自w的一个双向队列(支持FIFO/LIFOQ;在Q务生的子Q务,?x)被pushq当前工作线E所l护deque队列中,q入队列头部?/li>
  • 当一个工作线E的双向队列中暂无Q务时Q它?x)从随机的工作线E的双向队列的尾部获取一个入队最久的子Q?UC为窃?,take()方式获取Q先q先出的规则(FIFO)?/li>
  • 当一个工作线E遇C个join的操作,假如可能的话Q它?x)处理其他的dQ直到目标Q务被通知需要处理掉?/li>
  • 当一个工作者线E没有Q务可以处理,q且不能从其他工作者线E中H取的时Q它?x)后退(通过yields,sleeps,或者优先的调?,E后重试Q直到所有工作线E都?x)处于空闲状态,所有线E都?x)阻塞,{到另外的Q务在层被调用?/li>
Brian Goetz 认ؓ(f)"使用传统的线E池来实?fork-join 也具有挑战性,因ؓ(f) fork-joind线E生命周期的大部分时间花费在{待其他d上。这U行Z(x)造成U程饥饿死锁Qthread starvation deadlockQ,除非心选择参数以限制创建的d数量Q或者池本n非常大。传l的U程池是为相互独立的d设计的,而且设计中也考虑了潜在的d、粗_度d — fork-join 解决Ҏ(gu)不会(x)产生q两U情c(din)对于传l线E池的细_度dQ也存在所有工作线E共享的d队列发生争用的情c(din)?
下面谈一谈工作窃?work stealing)。在Fork/Join中,工作H取采用了一个被当做?Stack)使用的双端队列WorkQueue。双端队列WorkQueueQ支持在两端插入和移除元素,和单独的队列(Queue)相比Q多了一端。在Fork/Join中工作线E中被当做栈QStackQ来使用Q在头部push插入数据Qpop获取数。而尾部,可以供需要窃取的工作U程Qtake()Ҏ(gu)Q用。与单向队列相比Q减争用,可以提高性能?/div>
WorkQueue的定义:(x)
static final class WorkQueue {
......
}
它既没有l承自Deque又没有承Queue接口Q而是自己独立写了一个双端队列,数组实现。很昄Q数l的d性能要强于链表?br />看一下ForkJoinPool的默认构造函?
public ForkJoinPool() {
this(Runtime.getRuntime().availableProcessors(),
defaultForkJoinWorkerThreadFactory, null, false);
}

public static interface ForkJoinWorkerThreadFactory {
public ForkJoinWorkerThread newThread(ForkJoinPool pool);
}

static class DefaultForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new ForkJoinWorkerThread(pool);
}
}
在ForkJoinPool代码初始化时Q默认情况下Q?br />
defaultForkJoinWorkerThreadFactory =
new DefaultForkJoinWorkerThreadFactory();
默认情况下,Ҏ(gu)当前CPU的数量徏立一个ForkJoinWorkerThreadFactory工厂QCPU数量个ForkJoinWorkerThread工作U程?/div>
仔细看一下ForkJoinWorkerThread代码Q工作线E承自ThreadQ?/div>
很显ӞonStart ?onTermination为钩子函敎ͼ可以被重写,但,需要构造一个新的ForkJoinPool.ForkJoinWorkerThreadFactory来配合用。比如:(x)
public static void main(String[] args) {
ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() {
@Override
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new CustomedForkJoinWorkerThread(pool);
}
};

ForkJoinPool joinPool = new ForkJoinPool(Runtime.getRuntime()
.availableProcessors(), factory, null, false);
// some code here ...
}

private static final class CustomedForkJoinWorkerThread extends
ForkJoinWorkerThread {
protected CustomedForkJoinWorkerThread(ForkJoinPool pool) {
super(pool);
}

@Override
protected void onStart() {
super.onStart();

System.out.println("准备初始化资?..");
}

@Override
protected void onTermination(Throwable exception) {
System.out.println("开始清理资?..");

super.onTermination(exception);
}
}
接着看一下pool.runWorker(this)Ҏ(gu)Q?br />
final void runWorker(ForkJoinWorkerThread wt) {
WorkQueue w = wt.workQueue;
w.growArray(false);
w.seed = hashId(Thread.currentThread().getId());

do {} while (w.runTask(scan(w)));
}
初始化队列,讄其seed为当前线EID的哈希倹{然后@环执行,当没有Q务可获取Q自然就退Z。而scan()很复杂,大概功能Q从当前队列中获取元素,当前队列为空Ӟ从其他工作线E所持有的队列中H取一个。都没有Ӟ只能q回nullQ进而阻止线E活动?/div>
嗯,有时间会(x)再深入WorkQueue队列一些?/div>
  
  


nieyong 2012-02-08 21:35 发表评论
]]>Fork/Join模式(JSR166y)手记之斐波纳契数?Fibonacci)求解试http://www.aygfsteel.com/yongboy/archive/2012/02/07/369571.htmlnieyongnieyongTue, 07 Feb 2012 13:24:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/02/07/369571.htmlhttp://www.aygfsteel.com/yongboy/comments/369571.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/02/07/369571.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369571.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369571.html在参考资料中Q对斐LU_数列(Fibonacci)q行求解来展CRecursiveTask的用法,很好?/div>
另外Q在JSR166y演进的过E中Q其法l过调整Q导致原C代码中存在一些问题,需要进行些许调整。历史遗留代码,如下Q?br />
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
f2.fork();

return f2.join() + f1.join();
但现在已不徏议用。真要如此执行,?x)一直阻塞等待(臛_我本机是如此Q。查看RecursiveTask的源代码Q也发现Cdoc中,两个RecursiveTaskcdl果怺汇聚Q推荐示范ؓ(f)Q?/div>
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);

return f2.compute() + f1.join();
嗯,q里同时提供一个单U程版本的参考实玎ͼ与之作ؓ(f)Ҏ(gu)Q?/div>
在测试时Q发现速度太慢Q于是萌生了改进了其法的想法,于是一个非递归、单U程版本实现出现了:(x)

使用JUNIT 4q行试c:(x)

该脓(chung)的代码,都脓(chung)完了Q可以预一下哪一个算法的速度排名?Q嗯Q脓(chung)行JUNIT试输出l果吧:(x)
Fork/Join 法 ...
1836311903
用时 : 2203

单线E递归法 ...
1836311903
用时 : 1016

单线E改q递增法 ...
1836311903
用时 : 0
在测试类中,把MAX讄?5或更大的数字Q以上两个算法就可能{待q长的时_(d)实在没有耐心{待那么长时_(d)Q而算法三Q即使设|再大,也是瞬时完成?br />上面的测试类中,把results数组以static修饰Q公共共享方式,存放在常量区Q在速度上会(x)比原始测试代码读取方面更速,快了不少?br />本机的CPU双核的效果没有体现出来。权威一些的解析Q?br />
在Java 7 生命周期内,大的Q?2+Q多核系l将大量出现Q有了这个框架可以让Z对计密集型d获得相对单的增速方法。目前,forkjoin在如Sun Niagaras和Azulsq样的机器上工作得最好,它们只是卛_普及(qing)的ƈ行处理器。Forkjoin在标准SMP上工作的也不错。M来讲Q少?处理器的话你不ƈ能获得太多增速效?#8212;—其主要目标是针对成打到成癑֤理器范围?/blockquote>另一斚wQ也是Q务划分过于细,优势体现不出来。当Ӟ不是所有的d都适合F(tun)ork/Join模式Q以?qing)适合多线E,q具体d具体分析了?/div>

nieyong 2012-02-07 21:24 发表评论
]]>Fork/Join模式(JSR166y)手记之Phaserhttp://www.aygfsteel.com/yongboy/archive/2012/02/07/369572.htmlnieyongnieyongTue, 07 Feb 2012 09:34:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/02/07/369572.htmlhttp://www.aygfsteel.com/yongboy/comments/369572.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/02/07/369572.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369572.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369572.htmlq是一个综合了CountDownLatch和CyclicBarrierҎ(gu)的混合体,官方说灵zL非帔R。基本上Q只要对上面两个熟?zhn)Q那么阅读APIQ也不难快速上手的?/div>
yaofeng928 单ȝ其特点:(x)
Phaser同时包含CyclicBarrier和CountDownLatch两个cȝ功能。Phaser的arriveҎ(gu)将计数器加1QawaitAdvance线E阻塞,直到计数器达到目标,q两个方法与CountDownLatch的countDown和awaitҎ(gu)相对应;Phaser的arriveAndAwaitAdvanceҎ(gu)计数器?的同时将U程dQ直到计数器辑ֈ目标后l执行,q个Ҏ(gu)对应CyclicBarrier的awaitҎ(gu)?br />
除了包含以上两个cȝ功能外,Phaserq提供了更大的灵zL。CyclicBarrier和CountdownLatch在构造函数指定目标后无法修改,而Phaser提供了register和deregisterҎ(gu)可以对目标进行动态修攏V?/blockquote>
yaofeng928在他的博客文章中也提供了试CQ有兴趣着看看一看?/div>
在参考资料的W二个链接,则非常用心的l出对Phaser的用心解?/a>Q绝对值得一看,不过其代码存在些?dng)R误,但对M理解不生障?/div>
参考资料链?则给ZQ各U用场景?/div>
别h把自己所有想要理解的Q基本都上说出来Q不再需要单独写一,Ҏ(gu)推荐好了?/div>


nieyong 2012-02-07 17:34 发表评论
]]>Fork/Join模式(JSR166y)手记之ConcurrentLinkedDequehttp://www.aygfsteel.com/yongboy/archive/2012/02/06/369573.htmlnieyongnieyongMon, 06 Feb 2012 12:39:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/02/06/369573.htmlhttp://www.aygfsteel.com/yongboy/comments/369573.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/02/06/369573.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369573.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369573.htmlConcurrentLinkedDeque是JSR166y中新增的一个无界ƈ发Deque实现Q基于已链接节点的、Q选范围的双端队列。在q代Ӟ队列保持׃致性,但不?x)抛出ConcurrentModificationException异常?/div>
需要小心,与大多数 collection 不同Qsize Ҏ(gu)不是一个固定时间操作。由于这些队列的异步Ҏ(gu),定当前元素的数量需要遍历这些元素?/div>
另外Q一些批量操作,诸如 addAll, removeAll, retainAll, containsAll, equals, toArray{,不能够保证会(x)立刻执行。比如通过addAllҎ(gu)扚w提交若干元素Q于此同时另一U程在P代时Q可能只能访问到先前存在的元素?/div>
内存一致性效果:(x)当存在其他ƈ?collection Ӟ对象放?ConcurrentLinkedDeque 之前的线E中的操?happen-before 随后通过另一U程?ConcurrentLinkedDeque 讉K或移除该元素的操作?
先前存在一个线E安全ƈd的LinkedBlockingDeque实现Q现在好了,又多了个q发实现Q这样和Queue保持一_(d)q发和阻塞版本都h了。嗯Q果然是好事要成双?/div>
在用上没有什么可说的Q随时查看API DOCQ即可。刚开始以为Fork/Join的工作窃取(work stealingQ机制内部用ConcurrentLinkedDeque实现Q查看ForkJoinPool源代码时Q不曑֏现其w媄?/div>

nieyong 2012-02-06 20:39 发表评论
]]>Fork/Join模式(JSR166y)手记之ThreadLocalRandomhttp://www.aygfsteel.com/yongboy/archive/2012/02/04/369574.htmlnieyongnieyongSat, 04 Feb 2012 03:29:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/02/04/369574.htmlhttp://www.aygfsteel.com/yongboy/comments/369574.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/02/04/369574.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369574.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369574.htmlThreadLocalRandom是一个可以独立用的、用于生成随机数的类。承自RandomQ但性能过RandomQ所?#8220;青出于蓝而胜于蓝”。其API所提供Ҏ(gu)Q不多,父类Randomh的,它也一样具有。从表明看,是一个单例模式,其实不然Q?br />
private static final ThreadLocal localRandom =
new ThreadLocal() {
protected ThreadLocalRandom initialValue() {
return new ThreadLocalRandom();
}
};

ThreadLocalRandom() {
super();
initialized = true;
}


public static ThreadLocalRandom current() {
return localRandom.get();
}
采用ThreadLocalq行包装的Random子类Q每U程对应一个ThreadLocalRandom实例。测试代码:(x)
@Test
public void testInstance() {
final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
final List randomList = new ArrayList();
final Phaser barrier = new Phaser(1);

new Thread() {
@Override
public void run() {
randomList.add(ThreadLocalRandom.current());
barrier.arrive();
}
}.start();

barrier.awaitAdvance(barrier.getPhase());
if (randomList.isEmpty()) {
throw new NullPointerException();
}

Assert.assertTrue(threadLocalRandom != randomList.get(0));
}
q么一包装Q在性能上可以赶Math.random()Q不错?br />
@Test
public void testSpeed() {
final int MAX = 100000;
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();

long start = System.nanoTime();
for (int i = 0; i < MAX; i++) {
threadLocalRandom.nextDouble();
}
long end = System.nanoTime() - start;
System.out.println("use time1 : " + end);

long start2 = System.nanoTime();
for (int i = 0; i < MAX; i++) {
Math.random();
}
long end2 = System.nanoTime() - start2;
System.out.println("use time2 : " + end2);

Assert.assertTrue(end2 > end);
}
非规范的性能试Q某ơ输出结?
use time1 : 3878481
use time2 : 8633080
性能差别不止两倍啊Q哈哈?br />再看Math.random()Q其生成也是依赖于Randomc?
private static Random randomNumberGenerator;

private static synchronized void initRNG() {
if (randomNumberGenerator == null)
randomNumberGenerator = new Random();
}

public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}
很奇怪,性能Z么差那么q呢Q可能个各自的next函数不同造成。看一下Random中的next(int bits)Ҏ(gu)实现Q?br />
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
而ThreadLocalRandom的重写版本ؓ(f)Q?br />
protected int next(int bits) {  
rnd = (rnd * multiplier + addend) & mask;
return (int) (rnd >>> (48-bits));
}
相比ThreadLocalRandom的next(int bits)函数实现上更为简l,不存在seed的CAS操作Qƈ且少了很多的q算量?br />更ؓ(f)详细的机制研读,请阅d考资料中链接?/div>
另外QThreadLocalRandom 也提供了易用的,两个数字之间的随机数生成方式。类gQ?br />
nextDouble(double least, double bound)
nextInt(int least, int bound)
nextLong(long least, long bound)
随机数的生成范围?最?<= 随机?< 最大倹{可以包含最|但不包含最大倹{?
@Test
public void testHowtoUse(){
final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
final int MAX = 100;
int result = threadLocalRandom.nextInt(0, 100);
Assert.assertTrue(MAX > result);
}
嗯,q有Q不支持setSeedҎ(gu)?/div>
曄JDK 7中,ThreadLocalRandom 存在随机多个U程随机数生成相同的bugQ但最新版本中Q已不存在,被修复了,可以攑ֿ使用。从现在开始,完全可以使用ThreadLocalRandom替代RandomQ尤其是在ƈ发、ƈ行、多d{环境下Q会(x)比在多线E环境下使用公共׃n?span class="Apple-style-span" style="font-family: monospace;">Random对象实例更ؓ(f)有效?/span>
代码清单Q?/div>


nieyong 2012-02-04 11:29 发表评论
]]>Fork/Join模式(JSR166y)手记之TransferQueue/LinkedTransferQueuehttp://www.aygfsteel.com/yongboy/archive/2012/02/04/369575.htmlnieyongnieyongSat, 04 Feb 2012 03:28:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/02/04/369575.htmlhttp://www.aygfsteel.com/yongboy/comments/369575.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/02/04/369575.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369575.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369575.htmlTransferQueue是一个承了 BlockingQueue的接口,q且增加若干新的Ҏ(gu)。LinkedTransferQueue是实现类Q其定义Z个无界的队列Q一样具有先q先?FIFO : first-in-first-out)的特性?/div>
Doug Lea q样评h(hun)它:(x)
TransferQueue是一个聪明的队列Q它是ConcurrentLinkedQueue, SynchronousQueue (在公qx式下), 无界的LinkedBlockingQueues{的集?/blockquote>昄易见Q؜合了若干高Ҏ(gu),q且h高性能的一个组合体Q一个多面手?/div>
q里有一个有关LinkedTransferQueue的Doug Lea{h所撰写论文Q讨Z其算法、性能{,地址Qhttp://www.cs.rice.edu/~wns1/papers/2006-PPoPP-SQ.pdf
单纯从队列来看,TransferQueue接口增加了一些很实用的新Ҏ(gu),其transferҎ(gu)提供了线E之间直接交换对象的捷径Q下面一一说来?/div>
  1. transfer(E e)
    若当前存在一个正在等待获取的消费者线E,即立ȝ交之Q否则,?x)插入当前元素e到队列尾部,q且{待q入d状态,到有消费者线E取走该元素?span class="Apple-tab-span" style="white-space: pre;">
  2. tryTransfer(E e)
    若当前存在一个正在等待获取的消费者线E(使用take()或者poll()函数Q,使用该方法会(x)卛_转移/传输对象元素eQ?br />若不存在Q则q回falseQƈ且不q入队列?br />q是一个不d的操作?/li>
  3. tryTransfer(E e, long timeout, TimeUnit unit)
    若当前存在一个正在等待获取的消费者线E,?x)立即传输给?
    否则插入元素e到队列尾部,q且{待被消费者线E获取消Ҏ(gu),
    若在指定的时间内元素e无法被消费者线E获取,则返回falseQ同时该元素被移除?/li>
  4. hasWaitingConsumer()
    很明显,判断是否l端消费者线E?/li>
  5. getWaitingConsumerCount()
    字面意思很明白Q获取终端所有等待获取元素的消费U程数量
  6. size()
    因ؓ(f)队列的异步特性,当前队列的元素个数需要逐一q代Q可能会(x)得到一个不太准的l果Q尤其是在遍历时有可能队列发生更攏V?/li>
  7. 扚w操作
    cM?nbsp;addAllQremoveAll, retainAll, containsAll, equals, toArray {方法,API不能保证一定会(x)立刻执行?br />因此Q我们在使用q程中,不能有所期待Q这是一个具有异步特性的队列?/li>

注意事项Q?/strong>
  • 无论是transferq是tryTransferҎ(gu)Q在>=1个消费者线E等待获取元素时Q此旉列ؓ(f)I)Q都?x)立刻{交,q属于线E之间的元素交换。注意,q时Q元素ƈ没有q入队列?/li>
  • 在队列中已有数据情况下,transfer需要等待前面数据被消费掉,直到传递的元素e被消费线E取Cؓ(f)止?/li>
  • 使用transferҎ(gu)Q工作者线E可能会(x)被阻塞到生的元素被消费掉ؓ(f)?/li>
  • 消费者线E等待ؓ(f)零的情况下,各自的处理元素入队与否情冉|所不同?/li>
  • size()Ҏ(gu)Q需要P代,可能不太准确Q尽量不要调用?/li>

或许Q下ơ我们在构造一个线E池Ӟ可以考虑使用TransferQueueQ?br />
public static ExecutorService newTransferCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new LinkedTransferQueue());
}


单测试代?




nieyong 2012-02-04 11:28 发表评论
]]>Fork/Join模式(JSR166y)手记之JVAA6搭徏环境,开始学?/title><link>http://www.aygfsteel.com/yongboy/archive/2012/02/03/369576.html</link><dc:creator>nieyong</dc:creator><author>nieyong</author><pubDate>Fri, 03 Feb 2012 15:01:00 GMT</pubDate><guid>http://www.aygfsteel.com/yongboy/archive/2012/02/03/369576.html</guid><wfw:comment>http://www.aygfsteel.com/yongboy/comments/369576.html</wfw:comment><comments>http://www.aygfsteel.com/yongboy/archive/2012/02/03/369576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yongboy/comments/commentRss/369576.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yongboy/services/trackbacks/369576.html</trackback:ping><description><![CDATA[<div style="text-indent: 2em;">Doug Lea的jsr166yQ主要体现在Fork/Join模式Q分而治之,然后合ƈl果Q这么一U编E模式。相比JDK 1.6内置的JUCq发框架Q更加细_度。虽然已l内|JDK 1.7中,但本文环境基于JDK 1.6Q因此在相关包的引用斚wQ差异在于包的\径?/div><div style="text-indent: 2em;">有关Fork/Join的一些摘抄:(x)<br /><blockquote>fork/join框架是一?#8220;多核友好的、轻量q行框架 ”Q它支持q行~程风格Q将问题递归拆分成多个更片断,以ƈ行和调配的方式解冟뀂Fork-join融合了分而治之技术;获取问题后,递归地将它分成多个子问题Q直到每个子问题都够小Q以至于可以高效C行地解决它们。递归的过E将?x)把问题分成两个或者多个子问题Q然后把q些问题攑օ队列中等待处理(fork步骤Q,接下来等待所有子问题的结果(join步骤Q,把多个结果合q到一赗?/blockquote>Doug Lea描述了fork/join框架最可能的用场景和采用q程Q?br /><blockquote>MQ我期望其用曲U与其他q发工具雷同。最初,只有较少真正需要的Z用它们,但最l很难找C依赖于它们的E序Q它们常常深埋在底层基础架构lg中。因此,表面语法支持可能q不是那么重?#8212;—cd/lg开发者越是想合ƈ它们Q其用法是表现的笨拙?br />理想的情况下Q有几个使用层次Q?br />1. “q行做事”层次Q语a或工L(fng)译成q行代码Q同时检查安全?z跃性。这仍部分处于研I域?br /><br />2. 安排集合的ƈ行操作?#8212;—map、reduce、apply{等。那些想使用一ơ性操作特性操U集合的E序员们Q可以用这些特性来提高常用处理cd的速度。(q是ListTasks、ArrayTasks{等层次Q?br /><br />3. 手工生效forkjoin以解决特定问题。这是我正在全力投入的层ơ,以确保我们可能用工作窃取框架来支持范围q泛的ƈ行算法。(当前一些怪模怪样的和~Z解释的方法,如isQuiescent是ؓ(f)q种高用法设计的。多数程序只使用“fork”?#8220;join”Q但当你需要其他这些方法时Q它们也被提供了。)<br /><br />4. 扩展框架以创建新cd的ForkJoinTasks{等。例如,那些需要事务的操作。只有很量的hQ例如,或许是Fortressq行时类库开发者)需要这么做Q但是需要有_的基扩展钩子来才能做好?/blockquote>本文开始学?fn),按照心得步骤一步一步进行学?fn)。即开始?/div><div style="text-indent: 2em;">Doug Lea有关JUC的官|地址Qhttp://gee.cs.oswego.edu/dl/concurrency-interest/<br /><ol><li>下蝲原始代码Q?a >http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/cvs-root.tar.gz?parent=1&view=tar</a>Q到本地</li><li>把cvs-root.tar.gz解压到本地某个目录,假设解压地址是d:\workspace\jsr166</li><li>q入CMD命o(h)行,切换到d:\workspace\jsr166目录?/li><li>q行ANT命o(h)Qant jsr166ydist Q没讄ANT环境Q自行处理)</li><li>在dist目录生成jsr166y.jar文g、docs目录</li></ol></div><div style="text-indent: 2em;">在相关项目中加入jsr166y.jar依赖卛_?br />必备条gQJDK 1.6 </div><div style="text-indent: 2em;">机器配置Q?br /><blockquote>操作pȝ Windows XP 专业?32?SP3<br />处理? q?Pentium(奔腾) P6200 @ 2.13GHz<br />内存 4 GB ( 金士?DDR3 1333MHz / 三星 DDR3 1333MHz )</blockquote></div><div style="text-indent: 2em;">参考资?<br /><ol><li><a target="_blank">Java 7的ƈ行支持:(x)Fork/Join</a></li><li><a target="_blank">Java SE 7的新q发Ҏ(gu)?/a></li><li><a target="_blank">Adam Messinger谈Java 7?</a></li></ol></div><div style="text-indent: 2em;"></div><img src ="http://www.aygfsteel.com/yongboy/aggbug/369576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yongboy/" target="_blank">nieyong</a> 2012-02-03 23:01 <a href="http://www.aygfsteel.com/yongboy/archive/2012/02/03/369576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet 3.0W记之文件下载的那点事情http://www.aygfsteel.com/yongboy/archive/2012/01/19/369577.htmlnieyongnieyongThu, 19 Jan 2012 02:21:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/01/19/369577.htmlhttp://www.aygfsteel.com/yongboy/comments/369577.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/01/19/369577.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369577.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369577.html使用Servlet 3.0 提供文g下蝲Q当然了MServlet版本Q都可以做到Q这里仅仅作为知识的U篏。下面脓(chung)Z码,防止忘却?/div>

一。常规方式文件下载示?/h3>


很普通,单易用,不多说。一般情况下Q够用了?/div>

二。伪零拷?zero copy)方式文g下蝲C

变化不大Q关键代码在于:(x)利用
FileChannel.transferTo(long position, long count, WritableByteChannel target)
Ҏ(gu)辑ֈ零拷?zero copy)目的。把HttpServletResponse的输出对?ServletOutputStream)利用Channels.newChannel(OutputStream out)工具Q构Z个WritableByteChannel对象而已?/div>
OutputStream out = response.getOutputStream();
WritableByteChannel outChannel = Channels.newChannel(out);
试代码Q?/div>
心存疑虑的是Q这个是伪零拯方式实现。查看一下Channels.newChannel的源码:(x)
public static WritableByteChannel newChannel(final OutputStream out) {
if (out == null) {
throw new NullPointerException();
}

if (out instanceof FileOutputStream &&
FileOutputStream.class.equals(out.getClass())) {
return ((FileOutputStream)out).getChannel();
}

return new WritableByteChannelImpl(out);
}
因ؓ(f)输入的方法参Cؓ(f)ServletOutputStreamcd实例Q因此只能返回一个新构徏的WritableByteChannelImpl对象。具体构建:(x)
private static class WritableByteChannelImpl
extends AbstractInterruptibleChannel // Not really interruptible
implements WritableByteChannel
{
OutputStream out;
private static final int TRANSFER_SIZE = 8192;
private byte buf[] = new byte[0];
private boolean open = true;
private Object writeLock = new Object();

WritableByteChannelImpl(OutputStream out) {
this.out = out;
}

public int write(ByteBuffer src) throws IOException {
int len = src.remaining();
int totalWritten = 0;
synchronized (writeLock) {
while (totalWritten < len) {
int bytesToWrite = Math.min((len - totalWritten),
TRANSFER_SIZE);
if (buf.length < bytesToWrite)
buf = new byte[bytesToWrite];
src.get(buf, 0, bytesToWrite);
try {
begin();
out.write(buf, 0, bytesToWrite);
} finally {
end(bytesToWrite > 0);
}
totalWritten += bytesToWrite;
}
return totalWritten;
}
}

protected void implCloseChannel() throws IOException {
out.close();
open = false;
}
}
很显Ӟ也是属于内存cd的拷贝了Q只能算作伪零拷贝实C?/div>

三。{发到文g服务器上

一般常识ؓ(f)Q让最擅长的h来做最擅长的事情,是ؓ(f)高效。用类如Nginx高效的Web服务器专门处理文件下载业务,辑ֈ零拷贝的目的Q也是最x配组合。Nginx可以利用header元数据X-Accel-Redirect来控制文件下载行为,甚是不错。利用JAVAq行业务逻辑判断Q若W合规则Q则提交lNginxq行处理文g的下载,否则Q返回给l端用户权限不够{信息?/div>
用于控制用户是否h资格q行文g下蝲业务的控制器Q?/div>
当然Q这个仅仅用于演C,逻辑单。因为需要和nginx服务器进行配合,构徏一个ServerQ其配置文gQ?/div>
我们在nginx配置文g中,讄/dowloads/目录是不允许直接讉K的,必须l由/download/控制器进行{发方可。经试Q中文名不会(x)出现q问题Q保存的文g也是我们所h的文Ӟ同名Q也不会(x)出现q问题。但是,若在后台获取文g名,用于昄/输出Q则需要从ISO-8859-1解码成GBK~码方可?/div>
但这样做Q可能被l定到某个类型的服务器,但也值得。实际上切换到Apache也是很简单的?/div>
PS : Apache服务器诶则对应X-Sendfile头部属性,因很长时间不再用ApacheQ这里不再测试?br />源码下蝲


nieyong 2012-01-19 10:21 发表评论
]]>Servlet 3.0W记之Servlet的异步特性支持失效怎么办?http://www.aygfsteel.com/yongboy/archive/2012/01/18/369578.htmlnieyongnieyongWed, 18 Jan 2012 02:32:00 GMThttp://www.aygfsteel.com/yongboy/archive/2012/01/18/369578.htmlhttp://www.aygfsteel.com/yongboy/comments/369578.htmlhttp://www.aygfsteel.com/yongboy/archive/2012/01/18/369578.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/369578.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/369578.html满心Ƣ喜的ؓ(f)Servlet d上异步支持注解(asyncSupported = trueQ,不曾惻I其异步特性完全不起作用,仔细项目,发现存在一个编码拦截器QF(tun)ilterQ,虽用注解,但未标明支持异步Q导致被拦截的标注ؓ(f)异步支持的ServletQ异步特性皆失效。怎么办,在Filter中注解里面添加asyncSupported = true。问题解冟?/div>
但{念一惻I因历史原因,遗留pȝ?x)存在很多的Servlet 2.*规范的FilterQ无法支持异步,怎么办?全部手动修改为注解版本,可能不太现实。还好,Doug Lea的JUCq发包,为我们提供了一U实现思\?
实际步骤:
  1. 准备一个线E池
  2. 把当前请求相兛_性包装进一个Q务线E中
  3. 获取当前dU程执行l果Q不一定会(x)有返回|
  4. dQ执行完毕或时Q或被中断异常,可以输出客户?/li>
  5. 整个hl束
实际上,提交C个线E池的Q务线E,默认?x)返回一个Future对象Q利用Future对象的getҎ(gu)d的特性,当前h需要等待Q务线E执行的l束Q若指定旉内Q务线E顺利完成,则不必等到设定的旉的边界即可自然往下执行?/div>
实际代码Q?/div>
需要备注说明的是,若Future.get()无参敎ͼ则意味着需要等待计完成,然后获取其结果。这样可不用讑֮{待旉了。更多信息,请参考JDK?/div>

nieyong 2012-01-18 10:32 发表评论
]]>JAVAҎ(gu)g递OR引用传递,不过是Q云~http://www.aygfsteel.com/yongboy/archive/2010/11/25/346214.htmlnieyongnieyongThu, 25 Nov 2010 13:36:00 GMThttp://www.aygfsteel.com/yongboy/archive/2010/11/25/346214.htmlhttp://www.aygfsteel.com/yongboy/comments/346214.htmlhttp://www.aygfsteel.com/yongboy/archive/2010/11/25/346214.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/346214.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/346214.html对于JAVAҎ(gu)是g递,q是引用传递,有h一直以来争Z休。不如忘记这些提法,反而会(x)Ҏ(gu)理解一些?/p>

参数的传递分Zc:(x)

1。基本数据,变量是直接赋倹{?/p>

	public static void main(String[] args) {
int value = 0;
change(value);
System.out.println(value);
}

private static void change(int num) {
num = 99;
}


输出l果为:(x)0


可以q么认ؓ(f)Q在栈区 value 的Dl了一个生命周期很短的变量 numQ下面的事情是变量num的自家事情了?br />


2。对象参敎ͼ传递的是永q是对象的引用?/p>

public class ObjectTest {

public static void main(String[] args) {
Person p = new Person("Hi");

change(p);
System.out.println(p);
}

private static void change(Person per) {
per.setName("China");

per = new Person("english");
}
}

class Person {
public Person(String name) {
this.name = name;
}

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "name : " + getName();
}
}
q个例子最后输出结果ؓ(f)Q?strong>name Qchina

在栈区(stackQ,存在两个Person对象引用Q|
p把对象的引用地址赋值给了perQp也就完成了命;


per.setName("China"); q一句话意味着per操纵目标对象的setNameҎ(gu)。此时p和per都指向了同一个存攑֜堆区(heap)Person对象Q?/p>

per所引用的对象地址被重新赋|(x)per = new Person("english"); 自此per和p׃点关p都没有了:(x)p所指向的对象和per所指向的对象是两个不同的对象了?/p>

常见的基本数据数l也是一U对象?/p>

结Q无论是基本数据q是对象Q都是赋值操作,基本数据赋值直接在栈区q行Q对象只是把对象的引用地址赋|但对应同一个对象?/p>

有时间会(x)把图形附上,q样理解h?x)更形象一些?/p>

nieyong 2010-11-25 21:36 发表评论
]]>
分n一个免费的UML设计工具Q精版本的NetBeans 6.5http://www.aygfsteel.com/yongboy/archive/2010/10/27/346215.htmlnieyongnieyongWed, 27 Oct 2010 07:02:00 GMThttp://www.aygfsteel.com/yongboy/archive/2010/10/27/346215.htmlhttp://www.aygfsteel.com/yongboy/comments/346215.htmlhttp://www.aygfsteel.com/yongboy/archive/2010/10/27/346215.html#Feedback1http://www.aygfsteel.com/yongboy/comments/commentRss/346215.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/346215.html一直在L一个比较好使的UML设计工具Q尝试了若干Q感觉还是NetBeans提供的UML工具不错Q支持UML 2.0。至于Eclipse上面的UML插gQ也有尝试,一一攑ּ了?/p>

NetBeans 6.5对UML插g支持好一些,遂而去除里面很用到的插Ӟ只是保留了如下几个插Ӟ(x)

image

 

q样只能新徏java和uml目了,启动速度快了?/p>

image

有一点很赞的Q可以把某个设计模式的UMLcd直接调出来,在空白类图上点击右键Q选择“应用设计模式”Q?/p>

image 

在下面的步骤中,选择相应的模式即可:(x)

image

下面是责Q链模式对应的UML图:(x)

image 

打包下蝲地址Q?/p>

下蝲

QZ格式Q?5.9 MB大小Q解压后卛_使用?/p>

nieyong 2010-10-27 15:02 发表评论
]]>
建造者模式:(x)导向器封装生成品的具体步骤http://www.aygfsteel.com/yongboy/archive/2010/10/26/346216.htmlnieyongnieyongTue, 26 Oct 2010 09:36:00 GMThttp://www.aygfsteel.com/yongboy/archive/2010/10/26/346216.htmlhttp://www.aygfsteel.com/yongboy/comments/346216.htmlhttp://www.aygfsteel.com/yongboy/archive/2010/10/26/346216.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/346216.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/346216.htmlBuilder模式的缘P(x)
    假设创徏游戏中的一个房屋House设施Q该房屋的构建由几部分组成,且各个部分富于变化。如果用最直观的设计方法,每一个房屋部分的变化Q都导致房屋构建的重新修正.....
动机QMotivation):
    在Y件系l中Q有时候面临一?复杂对象"的创建工作,光常由各个部分的子对象用一定算法构?׃需求的变化Q这个复杂对象的各个部分l常面(f)着剧烈的变化,但是它们组合到一L(fng)法却相对稳定?
    如何应对U变化呢Q如何提供一U?装机制"来隔d"复杂对象的各个部?的变化,从而保持系l中?E_构徏法"不随需求的改变而改变?
意图(Intent)Q?/strong>
    一个复杂对象的构徏与其表示相分,使得同样的构E可以创Z同的表示?
UML 表示如下Q?
uml2
Builder模式

q里的Builder是一个抽象类Q不是接口,Zq一些属性和代码Q把E微变化的部分让子类来实玎ͼ昄Builder ?ConcreteOneProduct、ConcreteTwoProductl成了个模板模式Q?

先看建造?一个抽象类Q提供一些公用实?Builder.java)Q?
/**
 * 一个抽象来来替代接?/span>
 
 @author yongboy@gmail.com
 * @date 2010-10-26
 @version 1.0
 */
public abstract class Builder {
  protected Product product = null;

  public Builder() {
    product = new Product();
  }

  /**
   * 产生描述内容
   */
  public abstract void genDesc(String desc);

  /**
   * l制三角?/span>
   */
  public abstract void genTriangle(int len);

  /**
   * 输出最l生的产品
   
   @return
   */
  public Product getProduct() {
    return product;
  }
}

一个实玎ͼ主要是绘制三角ŞQ?
public class ConcreteOneBuilder extends Builder {

  @Override
  public void genDesc(String desc) {
    product.setDesc(desc);
  }

  @Override
  public void genTriangle(int len) {
    StringBuilder sb = new StringBuilder();
    for (int i = 1; i < len; i++) {
      for (int j = 0; j < i; j++) {
        sb.append(" *");
      }
      sb.append("\n");
    }

    product.setContent(sb.toString());
  }
}

W二个实玎ͼ(x)
public class ConcreteTwoBuilder extends Builder {

  @Override
  public void genDesc(String desc) {
    product.setDesc(desc);
  }

  @Override
  public void genTriangle(int len) {
    StringBuilder sb = new StringBuilder();

    for (int i = len; i > 0; i--) {
      int spaceNum = len - i;

      for (int j = 0; j < spaceNum; j++) {
        sb.append("  ");
      }
      for (int j = 0; j < i; j++) {
        sb.append(" *");
      }

      sb.append("\n");
    }

    product.setContent(sb.toString());
  }
}

产品定义:
/**
 * 一个有关三角的产品
 
 @author yongboy@gmail.com
 * @date 2010-10-26
 @version 1.0
 */
public class Product implements Serializable {
  private final static long serialVersionUID = 23536326475869L;

  /**
   * 当前产品的描q?/span>
   */
  private String desc;

  /**
   * 当前产品的详l内?/span>
   */
  private String content;

  public Product() {
  }

  public String getDesc() {
    return desc;
  }

  public void setDesc(String desc) {
    this.desc = desc;
  }

  public String getContent() {
    return content;
  }

  public void setContent(String content) {
    this.content = content;
  }

  public String toString() {
    return desc + "\n" + content;
  }
}

导向?装着产品生成的具体过E:(x)
/**
 * 导向器,装产品生生成过E?/span>
 
 @author yongboy@gmail.com
 * @date 2010-10-26
 @version 1.0
 */
public class Director {
  private Builder builder;
  private int MAX = 25;
  private int MIN = 10;

  public Director(Builder builder) {
    this.builder = builder;
  }

  public void construct() {
    int len = getNext();
    builder.genDesc("产品型号(" + getFormatNum(len")Q?);
    builder.genTriangle(len);
  }

  private int getNext() {
    return getRandomNum(MIN, MAX);
  }

  private static String getFormatNum(int num) {
    return String.format("0.%d", num);
  }
  
  /**
   * 产生两个C间的随机?/span>
   
   @param min
   @param max
   @return
   */
  private int getRandomNum(double min, double max) {
    return (intmin + (int) (Math.random() (max - min));
  }
}

客户端代码调用方式:(x)
public class Client {
  public static void main(String[] args) {
    Builder builder = new ConcreteOneBuilder();

    Director director = new Director(builder);

    director.construct();

    Product product = builder.getProduct();

    System.out.println(product);

    System.out.println();
    System.out.println("现在输出W二个?\n");
    System.out.println();

    builder = new ConcreteTwoBuilder();

    director = new Director(builder);

    director.construct();

    product = builder.getProduct();

    System.out.println(product);
  }
}

输入如下Q?br />
产品型号(0.23)Q?br /> *
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * *


现在输出W二个?


产品型号(0.17)Q?br /> * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * *
* * * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* *
*

每一ơ运行可能生成变形长度都?x)变好,q个变好有导向器q行控制着?br />
源文件下?/a>

nieyong 2010-10-26 17:36 发表评论
]]>
枚DQ不用那么单调,可以承担一些业务意?/title><link>http://www.aygfsteel.com/yongboy/archive/2010/10/22/346217.html</link><dc:creator>nieyong</dc:creator><author>nieyong</author><pubDate>Fri, 22 Oct 2010 03:52:00 GMT</pubDate><guid>http://www.aygfsteel.com/yongboy/archive/2010/10/22/346217.html</guid><wfw:comment>http://www.aygfsteel.com/yongboy/comments/346217.html</wfw:comment><comments>http://www.aygfsteel.com/yongboy/archive/2010/10/22/346217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yongboy/comments/commentRss/346217.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yongboy/services/trackbacks/346217.html</trackback:ping><description><![CDATA[Z大多手定义了一个枚举,仅仅是值的|列Q比如常见的一个,定义一个颜色枚举:(x) <br /><div><pre><span style="color: blue;">public</span> enum Color {<br /> RED,GREEN,BLUE<br />}</pre></div>Z很少Lq么一个问题:(x)枚D应该也可以承担一些业务意义。比如在q个Color枚D中,在某些情况下Q我们需要得到颜色的名称Qƈ且具有一个数字版本的IDQ若能提供一个随机的颜色值就更好不过了。怎么?Q?<br />大部分h们会(x)另徏立一个类Q提供几个方法,Ҏ(gu)举进行操作,以达到目的。但是这些方法本w应该是Color自n的一些动作,只是被割裂了。下面的代码p很好的完成以上要求:(x) <span id="Code_Open_Text_962449"></span><br /><span id="Code_Open_Text_962449"><div><pre><span style="color: blue;">public</span> enum Color {<br /> RED("<span style="color: darkred;">red</span>",1),GREEN("<span style="color: darkred;">green</span>",2),BLUE("<span style="color: darkred;">blue</span>",3);<br /> <br /> <span style="color: blue;">private</span> String name;<br /> <span style="color: blue;">private</span> <span style="color: blue;">int</span> id;<br /> <br /> <span style="color: green;">/**<br /> * 必须的,使用一个构造函数用以初始化枚D帔R<br /> * @param name<br /> * @param id<br /> */</span><br /> <span style="color: blue;">private</span> Color(String name, <span style="color: blue;">int</span> id){<br /> <span style="color: blue;">this</span>.name = name;<br /> <span style="color: blue;">this</span>.id = id;<br /> }<br /> <br /> <span style="color: blue;">public</span> String getName(){<br /> <span style="color: blue;">return</span> <span style="color: blue;">this</span>.name;<br /> }<br /> <br /> <span style="color: blue;">public</span> <span style="color: blue;">int</span> getId(){<br /> <span style="color: blue;">return</span> <span style="color: blue;">this</span>.id;<br /> }<br />}</pre></div>枚D是一个class变体Q类g <strong>RED("<span style="color: darkred;">red</span>",1) </strong>可以看做是定了一个初始化Color的一个实例,其构造方法签名具有两个参数需要传入? <br />现在的调用方式:(x) <br />Color.RED.getName(), Color.RED.getId() <br /> <br />嗯,~少了一个随机的颜色输出Ҏ(gu)Q下面我们在Color里面d如下代码Q? <br /> <div><pre> <span style="color: blue;">private</span> <span style="color: blue;">static</span> Random random = <span style="color: blue;">new</span> Random(47);<br /><br /> <span style="color: green;">/**<br /> * 随机提供一个颜?使用Ҏ(gu) Q?Color color = Color.random();<br /> * <br /> * @return Color<br /> */</span><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> Color random() {<br /> Color[] colors = Color.values();<br /> <span style="color: blue;">return</span> colors[random.nextInt(colors.length)];<br /> }</pre></div><br />要想提供一个随机的颜色|那就是静态的Q不是一个具体颜色的本n属性。枚N是具有values属性,q回一个数l。用方法ؓ(f)  <br /> <div><pre>Color color = Color.random();<br /><span style="color: green;">//一些属性的获取{操?/span></pre></div>有时Q我们需要传入一个颜色值字W串获得对应的枚丑ր? <br /> <div><pre> <span style="color: green;">/**<br /> * 构造一个MapQƈ初始化,便于插叙<br /> */</span><br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> Map<String, Color> clorNameMap = <span style="color: blue;">new</span> HashMap<String, Color>(<br /> Color.values().length);<br /> <span style="color: blue;">static</span> {<br /> <span style="color: blue;">for</span> (Color color : Color.values()) {<br /> clorNameMap.put(color.getName(), color);<br /> }<br /> }<br /> <br /> <span style="color: green;">/**<br /> * 通过颜色名称获取颜色枚D实例<br /> * @return<br /> */</span><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> Color getByName(String colorName){<br /> <span style="color: blue;">return</span> clorNameMap.get(colorName);<br /> }</pre></div>构造了一个私有的Map对象Q提升查询时的速度。用方? <br />Color color = Color.getByName(“red”); <br />若通过IDq行查询也可以按此方法,q里不再提供。下面ؓ(f)完整的代码:(x)</span><br /><div><span id="Code_Open_Text_962449"><br /> </span><br /><span id="Code_Open_Text_962449"></span><br /><span id="Code_Open_Text_962449"><div><pre><span style="color: blue;">import</span> java.util.HashMap;<br /><span style="color: blue;">import</span> java.util.Map;<br /><span style="color: blue;">import</span> java.util.Random;<br /><br /><span style="color: green;">/**<br /> * 枚D可以承担一些业务意?br /> * <br /> * @author yongboy@gmail.com<br /> * @date 2010-10-21<br /> */</span><br /><span style="color: blue;">public</span> enum Color {<br /> RED("<span style="color: darkred;">red</span>", 1), GREEN("<span style="color: darkred;">green</span>", 2), BLUE("<span style="color: darkred;">blue</span>", 3);<br /><br /> <span style="color: blue;">private</span> String name;<br /> <span style="color: blue;">private</span> <span style="color: blue;">int</span> id;<br /><br /> <span style="color: green;">/**<br /> * 必须的,使用一个构造函数用以初始化枚D帔R<br /> * <br /> * @param name<br /> * @param id<br /> */</span><br /> <span style="color: blue;">private</span> Color(String name, <span style="color: blue;">int</span> id) {<br /> <span style="color: blue;">this</span>.name = name;<br /> <span style="color: blue;">this</span>.id = id;<br /> }<br /><br /> <span style="color: blue;">public</span> String getName() {<br /> <span style="color: blue;">return</span> <span style="color: blue;">this</span>.name;<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">int</span> getId() {<br /> <span style="color: blue;">return</span> <span style="color: blue;">this</span>.id;<br /> }<br /><br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> Random random = <span style="color: blue;">new</span> Random(47);<br /><br /> <span style="color: green;">/**<br /> * 随机提供一个颜?使用Ҏ(gu) Q?Color color = Color.random();<br /> * <br /> * @return Color<br /> */</span><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> Color random() {<br /> Color[] colors = Color.values();<br /> <span style="color: blue;">return</span> colors[random.nextInt(colors.length)];<br /> }<br /><br /> <span style="color: green;">/**<br /> * 构造一个MapQƈ初始化,便于插叙<br /> */</span><br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> Map<String, Color> clorNameMap = <span style="color: blue;">new</span> HashMap<String, Color>(<br /> Color.values().length);<br /> <span style="color: blue;">static</span> {<br /> <span style="color: blue;">for</span> (Color color : Color.values()) {<br /> clorNameMap.put(color.getName(), color);<br /> }<br /> }<br /><br /> <span style="color: green;">/**<br /> * 通过颜色名称获取颜色枚D实例<br /> * <br /> * @return<br /> */</span><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> Color getByName(String colorName) {<br /> <span style="color: blue;">return</span> clorNameMap.get(colorName);<br /> }<br /><br /> <span style="color: blue;">public</span> String toString() {<br /> <span style="color: blue;">return</span> name + "<span style="color: darkred;">(</span>" + id + "<span style="color: darkred;">)</span>";<br /> }<br />}</pre><pre></pre></div>下面是UMLC意图:(x)<br /><a ><img alt="enum" src="http://lh4.ggpht.com/_iP4ZGnOhL6U/TNDWQGJneZI/AAAAAAAAAwc/S1WHNSaB__k/enum_thumb%5B1%5D.png?imgmax=800" style="border: 0px none; display: inline;" title="enum" border="0" /></a><br /><br />q里不是教大家获取枚丄一些编E技巧,那不是本意。只是想让一些看到本文的人注意一下:(x)枚D可以承担一些业务意义?</span></div><img src ="http://www.aygfsteel.com/yongboy/aggbug/346217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yongboy/" target="_blank">nieyong</a> 2010-10-22 11:52 <a href="http://www.aygfsteel.com/yongboy/archive/2010/10/22/346217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>观察者模式在U版Q订?发布模型的在U示?/title><link>http://www.aygfsteel.com/yongboy/archive/2010/10/19/346218.html</link><dc:creator>nieyong</dc:creator><author>nieyong</author><pubDate>Tue, 19 Oct 2010 02:14:00 GMT</pubDate><guid>http://www.aygfsteel.com/yongboy/archive/2010/10/19/346218.html</guid><wfw:comment>http://www.aygfsteel.com/yongboy/comments/346218.html</wfw:comment><comments>http://www.aygfsteel.com/yongboy/archive/2010/10/19/346218.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yongboy/comments/commentRss/346218.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yongboy/services/trackbacks/346218.html</trackback:ping><description><![CDATA[一直以来对观察者模?Observer)一直理解ؓ(f)订阅发布模式Q这h许更好理解一些。现实中的博客RSS定制Q在hpubsubhubbub未出C前,客户端都是被动的拉数据,PULL模式Q,需要客L(fng)d定时轮询方可。谷歌PUBSUBHUBBUB协议的问世,是一个创斎ͼRSSd推送的协议Q非常实Ӟ发布-订阅的最好典型? <br />观察者模式的详细定义以及(qing)相关理论Q可以参见《设计模式》,里面讲的很透彻? <br />本文带来一个在U版本的订阅-发布Q用h加一博文,所有订阅者可以马上得到通知Q主动推送方式,避免了系l的大量无谓h。虽有点PUBSUBHUBBUB协议的味道,但离实践q缺很多,是一个演C? <br />q个演示模拟的场景是兛_特定博主的所有订阅者可以在新的博文发表之后的瞬间得到通知。从博文的发布到通知所有的订阅者知晓,可以以毫U计(比较理想的情况下Q诸如服务器性能强劲Q网l好Q算法不错等Q。但q里的订阅者是有限制的Q必要有一个可以被内容发布者服务器回调的URL地址Q否则将不能实时通知到订阅者。这里强调的是可以被内容发布者服务器讉K。演C模拟的场景在一个机器上多个站点之间q行Q同一个局域网其它或者联|的环境下在理论上也都是可以的? <br />需要先d订阅者:(x) <br /><a ><img alt="dingyue" src="http://lh4.ggpht.com/_iP4ZGnOhL6U/TLz-4v3JOzI/AAAAAAAAAuI/c7aSv8xpOzI/dingyue_thumb%5B7%5D.png?imgmax=800" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="dingyue" border="0" height="207" width="776" /></a> <br />若退订,步骤相同Q致死要选择“退?#8221;卛_?br /><br /> <a ><img alt="dingyue" src="http://lh5.ggpht.com/_iP4ZGnOhL6U/TLz-7_LB3iI/AAAAAAAAAuQ/5mBJ_awWxN8/dingyue_thumb%5B5%5D.png?imgmax=800" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="dingyue" border="0" height="205" width="768" /></a> <br />q个表单可以攑֜其它订阅者站点下面,只是FORM的URL地址要正?br />q入站点首页卛_看到所有订阅者的回调地址Q? <br /><a ><img alt="home" src="http://lh4.ggpht.com/_iP4ZGnOhL6U/TLz--uAxpYI/AAAAAAAAAuY/wFFnYUX8PoY/home_thumb%5B1%5D.png?imgmax=800" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="home" border="0" height="295" width="779" /></a> <br /><br />有了订阅者之后,需要添加博文,试我们的订阅者? <br /><a ><img alt="Screenshot_2" src="http://lh3.ggpht.com/_iP4ZGnOhL6U/TLz_BU-lZYI/AAAAAAAAAug/vG9LZOW5QyE/Screenshot_2_thumb%5B2%5D.png?imgmax=800" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="Screenshot_2" border="0" height="588" width="523" /></a> <br /> <br /> <br />点击提交按钮之后Q在各个站点l端下即可看刎ͼ(x) <br /><a ><img alt="console" src="http://lh6.ggpht.com/_iP4ZGnOhL6U/TLz_GztWjTI/AAAAAAAAAuo/Ci4cx0S0nbU/console_thumb%5B5%5D.png?imgmax=800" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="console" border="0" height="737" width="731" /></a> <br />Z演示Q我们定义了两个订阅者站? subscribeOne和subscribeTwoQ一个显C所获取的数据,一个把获取的数据持久化到磁盘中? <br />下面看看ȝ点的一些代码,首先来一个传l意义上观察者模式?br />需要观察的对象Q即目标 BlogService.java<br /><div><pre><span style="color: green;">/**<br /> * 博文操作<br /> * @author yongboy@gmail.com<br /> * @date 2010-10-18<br /> * @version 1.0<br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> BlogService {<br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> Set<BlogObserver> obserserList;<br /><br /> <span style="color: blue;">static</span> {<br /> obserserList = <span style="color: blue;">new</span> HashSet<BlogObserver>();<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> addBlog(Blog blog) {<br /> System.out.println("<span style="color: darkred;">保存博文一些操?.....</span>");<br /> <span style="color: green;">// 忽略具体逻辑</span><br /> System.out.println("<span style="color: darkred;">执行通知到所有的订阅?...</span>");<br /> updateObsersers(blog);<br /> }<br /><br /> <span style="color: blue;">private</span> <span style="color: blue;">void</span> updateObsersers(Blog blog) {<br /> <span style="color: blue;">for</span> (BlogObserver server : obserserList) {<br /> server.update(blog);<br /> }<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> addObserver(BlogObserver blogObserver) {<br /> obserserList.add(blogObserver);<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> removeObserver(BlogObserver blogObserver) {<br /> obserserList.remove(blogObserver);<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> clearObserver() {<br /> obserserList.clear();<br /> }<br />}</pre><pre><br /></pre>可以看到内含观察者的一些简单的理操作?/div>q需要定义了一个观察者,接口实现Q?br /><br /><pre><span style="color: blue;">public</span> <span style="color: blue;">interface</span> BlogObserver {<br /> <span style="color: blue;">void</span> update(Blog blog);<br />}</pre><br />有两个具体的子类观察者,一个负责把博客的数据生成静态的文gQ但q个不是重点Q所以没有具体的代码附加Q另外一个观察者负责把新的博文通知到所有的订阅者?br /><span id="wmqeeuq" class="Apple-style-span" style="color: green; font-family: monospace;"><span id="wmqeeuq" class="Apple-style-span" style="white-space: pre;"><br /></span></span><br /><span id="wmqeeuq" class="Apple-style-span" style="color: green; font-family: monospace;"><span id="wmqeeuq" class="Apple-style-span" style="white-space: pre;">/**</span></span><br /><div><pre><span style="color: green;"> * 为新建的博文生成静态页?br /> * <br /> * @author yongboy@gmail.com<br /> * @date 2010-10-19<br /> * @version 1.0<br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> BlogGenPageObserver <span style="color: blue;">implements</span> BlogObserver {<br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> update(Blog blog) {<br /> <span style="color: green;">// 具体生成代码省略</span><br /> System.out.println("<span style="color: darkred;">博文静态页面观察者开始工?.....</span>");<br /> }<br />}</pre><span id="wmqeeuq" class="Apple-style-span" style="color: green; font-family: monospace;"><span id="wmqeeuq" class="Apple-style-span" style="white-space: pre;"><br /></span></span><br /><span id="wmqeeuq" class="Apple-style-span" style="color: green; font-family: monospace;"><span id="wmqeeuq" class="Apple-style-span" style="white-space: pre;">/**</span></span></div><div><pre><span style="color: green;"> * 定义一个博客信息推送观察?br /> * @author yongboy@gmail.com<br /> * @date 2010-10-18<br /> * @version 1.0<br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> BlogNotifyObserver <span style="color: blue;">implements</span> BlogObserver {<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> update(Blog blog) {<br /> System.out.println("<span style="color: darkred;">博文推送观察者开始工?.....</span>");<br /> <span style="color: green;">// 生成单篇博客的RSS</span><br /> RssService rssService = <span style="color: blue;">new</span> RssService(blog);<br /> String rssContent = rssService.ouputRss();<br /> <br /> <span style="color: green;">// 通知订阅者,分发博客内容</span><br /> NotifyService notifyService = <span style="color: blue;">new</span> NotifyService(rssContent);<br /> notifyService.doNotice();<br /> }<br />}</pre></div><br /><br />当前端发布了一博文后Q会(x)触发q两个观察者?br /><br />订阅-发布模型Q较适合于一个主端节点主动向各个订阅者节点主动推送信息,相比被动的拉模式Q更省网l带宽以?qing)服务器的性能?br />在一个范围较大的局域网之间Q彼此域之间的信息实旉知Q也?x)是一个较好的应用?br />在范围更大的互联|环境下Q一个具有相当大的数量订阅者的L可节省珍贵的机房带宽,l济收益不可觑?br /><br /><a target="_blank">源代码下?/a><img src ="http://www.aygfsteel.com/yongboy/aggbug/346218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yongboy/" target="_blank">nieyong</a> 2010-10-19 10:14 <a href="http://www.aygfsteel.com/yongboy/archive/2010/10/19/346218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>循环删除List数组容器里面元素http://www.aygfsteel.com/yongboy/archive/2010/10/09/346219.htmlnieyongnieyongSat, 09 Oct 2010 02:36:00 GMThttp://www.aygfsteel.com/yongboy/archive/2010/10/09/346219.htmlhttp://www.aygfsteel.com/yongboy/comments/346219.htmlhttp://www.aygfsteel.com/yongboy/archive/2010/10/09/346219.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/346219.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/346219.htmljava.util.ConcurrentModificationException
怎么办,实用M者会(x)把List数组转换成Iteratorq行q代删除Q一炚w题都没有Q?br />
 public static void main(String[] args) {
List<Student> students = pareStudents();

System.out.println("size : " + students.size());
System.out.println(students);

System.out.println("delete Student with name xiaoi");

Iterator<Student>stuIter = students.iterator();

while(stuIter.hasNext()){
Student stu = stuIter.next();
if(stu.getName().equals("xiaoi")){
stuIter.remove();
}
}

System.out.println("size : " + students.size());
System.out.println(students);
}

Iteratorq行循环操作Q然后删除,是很安全的。可以解决一些问题。但不要再用Iterator的时候用students.remove(stu)Q一样会(x)l出 java.util.ConcurrentModificationException 错误?br />

另一个方法就是重新构Z个List,把原先的students 数组作ؓ(f)参数传递进d可,虽然生成了一个全新的数组Q但都是Student对象的引用,多个引用的地址数组而已?br />


 public static void main(String[] args) {
List<Student> students = pareStudents();

System.out.println("size : " + students.size());
System.out.println(students);

System.out.println("delete Student with name xiaoi");
for(Student s : new ArrayList<Student>(students)){
if(s.getName().equals("xiaoi")){
students.remove(s);
}
}

System.out.println("size : " + students.size());
System.out.println(students);
}


需要那一U方式,那就自便了,个h們֐于用Iterator?br />完整试代码如下Q?br />
public class DeleteList {
private static class Student{
private String name;
private int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

public int hashCode() {
return name.hashCode();
}

public boolean equals(Object obj) {
if(obj == null || !(obj instanceof Student)){
return false;
}

Student objStu = (Student)obj;
return objStu.getName().equals(this.getName()) && objStu.getAge() == this.getAge();
}

public String toString(){
return name + " : " + age;
}
}

private static List<Student> pareStudents(){
ArrayList<Student> students = new ArrayList<Student>();

students.add(new Student("xiaoi", 18));
students.add(new Student("xiaoxin", 19));
students.add(new Student("john", 20));
students.add(new Student("xiaomei", 23));

return students;
}

public static void main(String[] args) {
List<Student> students = pareStudents();

System.out.println("size : " + students.size());
System.out.println(students);

System.out.println("delete Student with name xiaoi");
for(Student s : new ArrayList<Student>(students)){
if(s.getName().equals("xiaoi")){
students.remove(s);
}
}

System.out.println("size : " + students.size());
System.out.println(students);
}

public static void main2(String[] args) {
List<Student> students = pareStudents();

System.out.println("size : " + students.size());
System.out.println(students);

System.out.println("delete Student with name xiaoi");

Iterator<Student>stuIter = students.iterator();

while(stuIter.hasNext()){
Student stu = stuIter.next();
if(stu.getName().equals("xiaoi")){
stuIter.remove();
}
}

System.out.println("size : " + students.size());
System.out.println(students);
}
}

Iterator 是工作在一个独立的U程中,q且拥有一?mutex 锁?Iterator 被创Z后会(x)建立一个指向原来对象的单链索引表,当原来的对象数量发生变化Ӟq个索引表的内容不会(x)同步改变Q所以当索引指针往后移动的时候就找不到要q?代的对象Q所以按?fail-fast 原则 Iterator ?x)马上抛?/span> java.util.ConcurrentModificationException 异常?/span>

所?Iterator 在工作的时候是不允许被q代的对象被改变的。但你可以?Iterator 本n的方?remove() 来删除对象, Iterator.remove() Ҏ(gu)?x)在删除当前q代对象的同时维护烦引的一致性?/span>

refer url : http://www.cnblogs.com/iloveu/archive/2009/06/23/1509385.html


nieyong 2010-10-09 10:36 发表评论
]]>
模板模式以及(qing)java法的复?/title><link>http://www.aygfsteel.com/yongboy/archive/2010/10/06/346220.html</link><dc:creator>nieyong</dc:creator><author>nieyong</author><pubDate>Wed, 06 Oct 2010 02:59:00 GMT</pubDate><guid>http://www.aygfsteel.com/yongboy/archive/2010/10/06/346220.html</guid><wfw:comment>http://www.aygfsteel.com/yongboy/comments/346220.html</wfw:comment><comments>http://www.aygfsteel.com/yongboy/archive/2010/10/06/346220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yongboy/comments/commentRss/346220.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yongboy/services/trackbacks/346220.html</trackback:ping><description><![CDATA[针对常用的算法进行重新复?fn)了一下,l合对象数组排序Q用模板模式封装了一部分Q各个子cd现自q对象数组排序法。里面稍微涉?qing)到了适配器、策略模式等。用了泛型Q嗯Q会(x)带来一部分代码的复用?br />定义一个算法抽象基c:(x)<br /><div><pre><span style="color: green;">/**<br /> * 对象数组排序法Q藉此复?fn)几U常见排序算?br /> * <br /> * 模板模式<br /> * <br /> **/</span><br /><span style="color: blue;">public</span> <span style="color: blue;">abstract</span> <span style="color: blue;">class</span> Sort {<br /><br /> <span style="color: green;">/**<br /> * 对象数组排序<br /> * @param <T><br /> * @param ts 传入要排序的对象数组<br /> * @param c 需要传入的自定义比较器<br /> */</span><br /> <span style="color: blue;">public</span> <span style="color: blue;">abstract</span> <T> <span style="color: blue;">void</span> sort(T[] ts, Comparator<? <span style="color: blue;">super</span> T> c);<br /><br /> <span style="color: green;">/**<br /> * 对象数组排序<br /> * @param <T><br /> * @param datas 传入的对象必dl实CComparable接口<br /> */</span><br /> <span style="color: blue;">public</span> <T <span style="color: blue;">extends</span> Comparable<T>> <span style="color: blue;">void</span> sort(T[] datas) {<br /> sort(datas, <span style="color: blue;">new</span> ComparatorAdapter<T>());<br /> }<br /><br /> <span style="color: green;">/**<br /> * 定义一个比较适配器内部类,使Comparable接口适配成Comparator接口<br /> * <br /> * @author xiaomin<br /> * <br /> * @param <T><br /> */</span><br /> <span style="color: blue;">private</span> <span style="color: blue;">class</span> ComparatorAdapter<T <span style="color: blue;">extends</span> Comparable<T>> <span style="color: blue;">implements</span><br /> Comparator<T> {<br /> <span style="color: blue;">public</span> <span style="color: blue;">int</span> compare(T o1, T o2) {<br /> <span style="color: blue;">return</span> o1.compareTo(o2);<br /> }<br /> }<br /><br /> <span style="color: green;">/**<br /> * 交换对象数组里面的两个元素位|?br /> * @param <T><br /> * @param ints<br /> * @param index1<br /> * @param index2<br /> */</span><br /> <span style="color: blue;">protected</span> <T> <span style="color: blue;">void</span> swap(T[] ints, <span style="color: blue;">int</span> index1, <span style="color: blue;">int</span> index2) {<br /> T temp = ints[index1];<br /><br /> ints[index1] = ints[index2];<br /><br /> ints[index2] = temp;<br /> }<br />}</pre></div>一个冒泡算法实玎ͼ(x)<br /><div><pre><span style="color: green;">/**<br /> * 冒排序----交换排序的一U?br /> * Ҏ(gu)Q相M元素q行比较Q如有需要则q行交换Q每完成一ơ@环就最大元素排在最后(如从到大排序)Q下一ơ@环是其他的数进行类似操作?br /> * 性能Q比较次数O(n^2),n^2/2Q交换次数O(n^2),n^2/4<br /> *<br />**/</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> Bubble <span style="color: blue;">extends</span> Sort{<br /><br /> @Override<br /> <span style="color: blue;">public</span> <T> <span style="color: blue;">void</span> sort(T[] datas, Comparator<? <span style="color: blue;">super</span> T> c){<br /> <span style="color: blue;">for</span>(<span style="color: blue;">int</span> i = (datas.length - 1); i > 0; i--){<br /> <span style="color: blue;">for</span>(<span style="color: blue;">int</span> j = 0; j < i; j++){<br /> <span style="color: blue;">if</span>(c.compare(datas[j], datas[j + 1]) > 0){<br /> <span style="color: blue;">super</span>.swap(datas, j, j+1);<br /> }<br /> }<br /> }<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> main(String ... args){<br /> Bubble b = <span style="color: blue;">new</span> Bubble();<br /> Integer [] ints = {1, 23, 0, 2, 356, 367, 6,-1, 256};<br /> b.sort(ints);<br /> <br /> System.out.println(Arrays.toString(ints));<br /> }<br />}</pre></div>一个插入排序:(x)<br /><div><pre><span style="color: green;">/**<br /> * 插入排序<br /> * Ҏ(gu)Q将一个记录插入到已排好序的有序表Q有可能是空表)?从而得C个新的记录数?的有序表?br /> * 性能Q比较次数O(n^2),n^2/4<br /> * 复制ơ数O(n),n^2/4<br /> * 比较ơ数是前两者的一般,而复制所需的CPU旉较交换少Q所以性能上比冒排序提高一倍多Q而比选择排序也要快?br /> *<br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> Insert <span style="color: blue;">extends</span> Sort{<br /><br /> @Override<br /> <span style="color: blue;">public</span> <T> <span style="color: blue;">void</span> sort(T[] datas, Comparator<? <span style="color: blue;">super</span> T> c){<br /> <span style="color: blue;">for</span>(<span style="color: blue;">int</span> i = 0; i < datas.length; i++){<br /> <span style="color: blue;">for</span>(<span style="color: blue;">int</span> j = i; j > 0; j--){<br /> <span style="color: blue;">if</span>(c.compare(datas[j -1],datas[j]) > 0){<br /> <span style="color: blue;">super</span>.swap(datas, j-1, j);<br /> }<br /> }<br /> }<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> main(String [] args){<br /> Insert insert = <span style="color: blue;">new</span> Insert();<br /> Double [] doubles = {1.0, 0.3, 3.4, -0.3, 3.0,3.0, 0.34};<br /> <br /> insert.sort(doubles);<br /> <br /> System.out.println(Arrays.toString(doubles));<br /> }<br />}</pre></div>其它两个Q快速,选择排序不再一一_脓(chung)?br />附加一个客L(fng)试c:(x)<br /><div><pre><span style="color: blue;">public</span> <span style="color: blue;">class</span> Client {<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> main(String[] args) {<br /> Person[] persons = { <span style="color: blue;">new</span> Person("<span style="color: darkred;">a</span>", 12), <span style="color: blue;">new</span> Person("<span style="color: darkred;">b</span>", 10),<br /> <span style="color: blue;">new</span> Person("<span style="color: darkred;">demo</span>", 23), <span style="color: blue;">new</span> Person("<span style="color: darkred;">hello</span>", 22),<br /> <span style="color: blue;">new</span> Person("<span style="color: darkred;">hello</span>", 32), <span style="color: blue;">new</span> Person("<span style="color: darkred;">xiaomeng</span>", 2) };<br /> <br /> Person [] selectPersons = persons.clone();<br /> <br /> Person [] quickPersons = persons.clone();<br /> <br /> Person [] quickCustomPersons = persons.clone();<br /> <br /> Person [] insertPersons = persons.clone();<br /><br /> System.out.println("<span style="color: darkred;">排序?......</span>");<br /> System.out.println(Arrays.toString(persons));<br /> System.out.println();<br /> <br /> System.out.println("<span style="color: darkred;">冒排序?......</span>");<br /> <span style="color: blue;">new</span> Bubble().sort(persons);<br /> System.out.println(Arrays.toString(persons));<br /> System.out.println(); <br /><br /> System.out.println("<span style="color: darkred;">选择排序?......</span>");<br /> <span style="color: blue;">new</span> Select().sort(selectPersons);<br /> System.out.println(Arrays.toString(selectPersons));<br /> System.out.println();<br /> <br /> System.out.println("<span style="color: darkred;">插入排序?......</span>");<br /> <span style="color: blue;">new</span> Insert().sort(insertPersons);<br /> System.out.println(Arrays.toString(insertPersons));<br /> System.out.println();<br /> <br /> System.out.println("<span style="color: darkred;">快速排序后 ......</span>");<br /> <span style="color: blue;">new</span> Quick().sort(quickPersons);<br /> System.out.println(Arrays.toString(quickPersons));<br /> System.out.println();<br /><br /> System.out.println("<span style="color: darkred;">使用快速自定义排序 ......</span>");<br /> <span style="color: blue;">new</span> Quick().sort(quickCustomPersons, <span style="color: blue;">new</span> Comparator<Person>() {<br /> <span style="color: blue;">public</span> <span style="color: blue;">int</span> compare(Person o1, Person o2) {<span style="color: green;">// 倒叙排列 </span><br /> <span style="color: blue;">return</span> o1.getAge() > o2.getAge() ? -1 : (o1.getAge() == o2.getAge() ? 0 : 1);<br /> }<br /> });<br /><br /> System.out.println(Arrays.toString(quickCustomPersons));<br /> }<br />}<br /><br /><span style="color: blue;">class</span> Person <span style="color: blue;">implements</span> Serializable, Comparable<Person> {<br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">final</span> <span style="color: blue;">long</span> serialVersionUID = -23536L;<br /> <br /> <span style="color: blue;">private</span> String name;<br /> <span style="color: blue;">private</span> <span style="color: blue;">int</span> age;<br /><br /> <span style="color: blue;">public</span> Person() {<br /> }<br /><br /> <span style="color: blue;">public</span> Person(String name, <span style="color: blue;">int</span> age) {<br /> <span style="color: blue;">this</span>.name = name;<br /> <span style="color: blue;">this</span>.age = age;<br /> }<br /><br /> <span style="color: blue;">public</span> String getName() {<br /> <span style="color: blue;">return</span> name;<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> setName(String name) {<br /> <span style="color: blue;">this</span>.name = name;<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">int</span> getAge() {<br /> <span style="color: blue;">return</span> age;<br /> }<br /><br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> setAge(<span style="color: blue;">int</span> age) {<br /> <span style="color: blue;">this</span>.age = age;<br /> }<br /> <br /> <span style="color: green;">// 正序排列</span><br /> <span style="color: blue;">public</span> <span style="color: blue;">int</span> compareTo(Person o) {<br /> <span style="color: blue;">if</span> (o == <span style="color: blue;">null</span>)<br /> <span style="color: blue;">return</span> -1;<br /><br /> <span style="color: blue;">return</span> <span style="color: blue;">this</span>.getAge() < o.getAge() ? -1 : (<span style="color: blue;">this</span>.getAge() == o.getAge() ? 0 : 1);<br /> }<br /><br /> <span style="color: blue;">public</span> String toString() {<br /> <span style="color: blue;">return</span> "<span style="color: darkred;">name : </span>" + getName() + "<span style="color: darkred;"> age : </span>" + getAge();<br /> }<br />}</pre><pre><br /></pre></div>代码打包下蝲地址: <a target="_blank">下蝲</a><br /><br /><br /><br /><br /><img src ="http://www.aygfsteel.com/yongboy/aggbug/346220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yongboy/" target="_blank">nieyong</a> 2010-10-06 10:59 <a href="http://www.aygfsteel.com/yongboy/archive/2010/10/06/346220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA 两种排序方式复习(fn)http://www.aygfsteel.com/yongboy/archive/2010/10/05/346221.htmlnieyongnieyongTue, 05 Oct 2010 09:24:00 GMThttp://www.aygfsteel.com/yongboy/archive/2010/10/05/346221.htmlhttp://www.aygfsteel.com/yongboy/comments/346221.htmlhttp://www.aygfsteel.com/yongboy/archive/2010/10/05/346221.html#Feedback0http://www.aygfsteel.com/yongboy/comments/commentRss/346221.htmlhttp://www.aygfsteel.com/yongboy/services/trackbacks/346221.html传统模式下的两种排序法Q?br />
/**
* JAVA两种排序复习(fn)
* 针对具体对象~写相应的排序代码,q一部分是经常变动的部分
* 排序Arrays.sortҎ(gu)Z变的部分Q封装了具体排序法
* 两者结合,一个策略模式出来了
*
* @author xiaomin
*/

public class Person implements Serializable, Comparable<Person> {
private static final long serialVersionUID = -23536L;

private String name;
private int age;

public Person() {
}

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

// 正序排列,针对具体bean的排?l常变动的部?/span>
public int compareTo(Person o) {
if (o == null)
return -1;

return this.getAge() < o.getAge() ? -1 : (this.getAge() == o.getAge() ? 0 : 1);
}

public String toString() {
return "name : " + getName() + " age : " + getAge();
}

public static void main(String... args) {
Person[] persons = { new Person("a", 12), new Person("b", 10),
new Person("demo", 23), new Person("hello", 22),
new Person("hello", 32) };

System.out.println("排序?......");
System.out.println(Arrays.toString(persons));

System.out.println("排序?......");
Arrays.sort(persons);
System.out.println(Arrays.toString(persons));

System.out.println("使用自定义排?......");

// 适用于没有承Comparable的bean或需要自行定制的排序方式
Arrays.sort(persons, new Comparator<Person>() {
public int compare(Person o1, Person o2) {// 倒叙排列
return o1.getAge() > o2.getAge() ? -1 : (o1.getAge() == o2.getAge() ? 0 : 1);
}
});

System.out.println(Arrays.toString(persons));
}
}

一般还是徏议用JQO内置的排序算法,当然我们q是可以自己~写自定义的排序法Q下面代码仅仅ؓ(f)了演C?/div>
/**
* 自定义冒泡排序算法,演示使用Q用以替代系l默认的Arrays.sort
* @author xiaomin
*
*/

public class BubbleSort {
public static void main(String[] args) {
Person[] persons = { new Person("a", 12), new Person("b", 10),
new Person("demo", 23), new Person("hello", 22),
new Person("hello", 32) };

System.out.println("排序?......");
System.out.println(Arrays.toString(persons));

System.out.println("排序?......");
bubble(persons);
System.out.println(Arrays.toString(persons));

System.out.println("使用自定义排?......");

// 适用于没有承Comparable的bean或需要自行定制的排序方式
bubble(persons, new Comparator<Person>() {
public int compare(Person o1, Person o2) {// 倒叙排列
return o1.getAge() > o2.getAge() ? -1 : (o1.getAge() == o2.getAge() ? 0 : 1);
}
});

System.out.println(Arrays.toString(persons));
}

public static <T> void bubble(T [] ts, Comparator<? super T> c){
for(int i = 0; i < ts.length; i ++){
for(int j = ts.length -1; j > i; j--){
if(c.compare(ts[j-1], ts[j]) > 0){
swap(ts, j-1, j);
}
}
}
}

public static <T extends Comparable<T>> void bubble(T [] ts){
for(int i = 0; i < ts.length; i ++){
for(int j = ts.length -1; j > i; j--){
if(ts[j-1].compareTo(ts[j]) > 0){
swap(ts, j-1, j);
}
}
}
}

private static <T> void swap(T [] ints,int index1, int index2){
T temp = ints[index1];

ints[index1] = ints[index2];

ints[index2] = temp;
}
}
 
两种排序输出l果Q?/pre>
排序?......
[name : a age : 12, name : b age : 10, name : demo age : 23, name : hello age : 22, name : hello age : 32]
排序?......
[name : b age : 10, name : a age : 12, name : hello age : 22, name : demo age : 23, name : hello age : 32]
使用自定义排?......
[name : hello age : 32, name : demo age : 23, name : hello age : 22, name : a age : 12, name : b age : 10]

若有旉Q也可以实现其它常见的排序算法?/em>

关于 Arrays的Sort法分析 Q?http://www.slideshare.net/zianed/arrayssort 可以参考一下?img src ="http://www.aygfsteel.com/yongboy/aggbug/346221.html" width = "1" height = "1" />

nieyong 2010-10-05 17:24 发表评论
]]>JAVA StackQ栈Q学?fn)代?/title><link>http://www.aygfsteel.com/yongboy/archive/2010/10/05/346222.html</link><dc:creator>nieyong</dc:creator><author>nieyong</author><pubDate>Tue, 05 Oct 2010 03:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/yongboy/archive/2010/10/05/346222.html</guid><wfw:comment>http://www.aygfsteel.com/yongboy/comments/346222.html</wfw:comment><comments>http://www.aygfsteel.com/yongboy/archive/2010/10/05/346222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yongboy/comments/commentRss/346222.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yongboy/services/trackbacks/346222.html</trackback:ping><description><![CDATA[q日了解一下栈的概念,LIFOQ后q先出,手写了几个实现Q添加泛型支持,特脓(chung)于此Q?br /><br /><div><pre>/**<br /> * 定义一个不可变?br /> * <br /> * @author xiaomin<br /> * <br /> * @param <span style="color: blue;"><</span><span style="color: maroon;">T</span><span style="color: blue;">></span><br /> */<br />public class DefaultStack<span style="color: blue;"><</span><span style="color: maroon;">T</span> <span style="color: red;">extends</span> <span style="color: red;">Serializable</span><span style="color: blue;">></span> implements Stack<span style="color: blue;"><</span><span style="color: maroon;">T</span><span style="color: blue;">></span> {<br /><br /> private int size;<br /><br /> private Object[] values;<br /><br /> private int curr;<br /><br /> public DefaultStack(int size) {<br /> this.size = size;<br /><br /> curr = -1;<br /><br /> values = new Object[size];<br /> }<br /><br /> @Override<br /> public void push(T t) {<br /> if ((size - 1) == curr) {<br /> throw new UnsupportedOperationException("The Stack is full now !");<br /> }<br /><br /> curr++;<br /> values[curr] = t;<br /> }<br /><br /> @SuppressWarnings("unchecked")<br /> @Override<br /> public T pop() {<br /> if (curr <span style="color: blue;"><</span> 0) {<br /> throw new UnsupportedOperationException("The Stack is empty now !");<br /> }<br /><br /> return (T) values[curr--];<br /> }<br /><br /> @Override<br /> public boolean end() {<br /> return curr == -1;<br /> }<br />}</pre></div>有三个实玎ͼ(x)<br /><div><pre><span style="color: green;">/**<br /> * 定义一个链接结构的?br /> * <br /> * @author xiaomin<br /> * <br /> * @param <T><br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> LinkStack<T <span style="color: blue;">extends</span> Serializable> <span style="color: blue;">implements</span> Stack<T> {<br /><br /> <span style="color: green;">/**<br /> * 定义一个节?br /> * <br /> * @author xiaomin<br /> * <br /> */</span><br /> <span style="color: blue;">private</span> <span style="color: blue;">class</span> Node <span style="color: blue;">implements</span> Serializable {<br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">final</span> <span style="color: blue;">long</span> serialVersionUID = 1L;<br /><br /> <span style="color: blue;">private</span> T value;<br /> <span style="color: blue;">private</span> Node pre;<br /><br /> <span style="color: green;">// 构造一个空?/span><br /> <span style="color: blue;">public</span> Node() {<br /> value = <span style="color: blue;">null</span>;<br /> pre = <span style="color: blue;">null</span>;<br /> }<br /><br /> <span style="color: blue;">public</span> Node(T value, Node pre) {<br /> <span style="color: blue;">this</span>.value = value;<br /> <span style="color: blue;">this</span>.pre = top;<br /> }<br /> }<br /><br /> <span style="color: blue;">private</span> Node top = <span style="color: blue;">new</span> Node();<br /><br /> @Override<br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> push(T t) {<br /> top = <span style="color: blue;">new</span> Node(t, top);<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> T pop() {<br /> T value = top.value;<br /><br /> <span style="color: blue;">if</span> (!end())<br /> top = top.pre;<br /><br /> <span style="color: blue;">return</span> value;<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> <span style="color: blue;">boolean</span> end() {<br /> <span style="color: blue;">return</span> top.value == <span style="color: blue;">null</span> && top.pre == <span style="color: blue;">null</span>;<br /> }<br />}</pre></div><br /><div><pre><span style="color: green;">/**<br /> * 定义一个不可变?br /> * <br /> * @author xiaomin<br /> * <br /> * @param <T><br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> DefaultStack<T <span style="color: blue;">extends</span> Serializable> <span style="color: blue;">implements</span> Stack<T> {<br /><br /> <span style="color: blue;">private</span> <span style="color: blue;">int</span> size;<br /><br /> <span style="color: blue;">private</span> Object[] values;<br /><br /> <span style="color: blue;">private</span> <span style="color: blue;">int</span> curr;<br /><br /> <span style="color: blue;">public</span> DefaultStack(<span style="color: blue;">int</span> size) {<br /> <span style="color: blue;">this</span>.size = size;<br /><br /> curr = -1;<br /><br /> values = <span style="color: blue;">new</span> Object[size];<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> push(T t) {<br /> <span style="color: blue;">if</span> ((size - 1) == curr) {<br /> <span style="color: blue;">throw</span> <span style="color: blue;">new</span> UnsupportedOperationException("<span style="color: darkred;">The Stack is full now !</span>");<br /> }<br /><br /> curr++;<br /> values[curr] = t;<br /> }<br /><br /> @SuppressWarnings("<span style="color: darkred;">unchecked</span>")<br /> @Override<br /> <span style="color: blue;">public</span> T pop() {<br /> <span style="color: blue;">if</span> (curr < 0) {<br /> <span style="color: blue;">throw</span> <span style="color: blue;">new</span> UnsupportedOperationException("<span style="color: darkred;">The Stack is empty now !</span>");<br /> }<br /><br /> <span style="color: blue;">return</span> (T) values[curr--];<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> <span style="color: blue;">boolean</span> end() {<br /> <span style="color: blue;">return</span> curr == -1;<br /> }<br />}</pre></div><br /><div><pre><span style="color: green;">/**<br /> * 定义一个容量可变的?br /> * <br /> * @author xiaomin<br /> * <br /> * @param <T><br /> */</span><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> ListStack<T <span style="color: blue;">extends</span> Serializable> <span style="color: blue;">implements</span> Stack<T> {<br /><br /> <span style="color: blue;">private</span> List<T> list = <span style="color: blue;">null</span>;<br /><br /> <span style="color: blue;">public</span> ListStack() {<br /> list = <span style="color: blue;">new</span> ArrayList<T>();<br /> }<br /><br /> <span style="color: blue;">public</span> ListStack(<span style="color: blue;">int</span> size) {<br /> list = <span style="color: blue;">new</span> ArrayList<T>(size);<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> <span style="color: blue;">void</span> push(T t) {<br /> list.add(t);<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> T pop() {<br /> <span style="color: blue;">if</span> (list.isEmpty()) {<br /> <span style="color: blue;">throw</span> <span style="color: blue;">new</span> EmptyStackException();<br /> }<br /><br /> <span style="color: blue;">return</span> list.remove(list.size() - 1);<br /> }<br /><br /> @Override<br /> <span style="color: blue;">public</span> <span style="color: blue;">boolean</span> end() {<br /> <span style="color: blue;">return</span> list.isEmpty();<br /> }<br />}</pre></div><br />试代码如下Q?br /><div><pre> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> main(String[] args) {<br /> System.out.println("<span style="color: darkred;">link stack ...\n</span>");<br /><br /> Stack<Integer> linkStack = <span style="color: blue;">new</span> LinkStack<Integer>();<br /> <span style="color: blue;">int</span> times = 10;<br /><br /> testMethod(linkStack, times);<br /><br /> System.out.println("<span style="color: darkred;">\ndefault stack ...\n</span>");<br /> Stack<Integer> defaultStack = <span style="color: blue;">new</span> DefaultStack<Integer>(times);<br /> <br /> testMethod(defaultStack, times);<br /> <br /> System.out.println("<span style="color: darkred;">\nlist stack with enouch space...\n</span>");<br /> Stack<Integer> listStack = <span style="color: blue;">new</span> ListStack<Integer>();<br /><br /> testMethod(listStack, times*2);<br /> }<br /><br /> <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> testMethod(Stack<Integer> linkStack, <span style="color: blue;">int</span> times) {<br /> Random random = <span style="color: blue;">new</span> Random(47);<br /><br /> <span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i < times; i++) {<br /> <span style="color: blue;">int</span> value = i * random.nextInt(times);<br /><br /> System.out.println("<span style="color: darkred;">节点 </span>" + (i + 1) + "<span style="color: darkred;"> : </span>" + value);<br /><br /> linkStack.push(value);<br /> }<br /><br /> System.out.println("<span style="color: darkred;">*********************************</span>");<br /><br /> <span style="color: blue;">int</span> nums = times;<br /> <span style="color: blue;">while</span> (!linkStack.end()) {<br /> System.out.println("<span style="color: darkred;">节点 </span>" + (nums--) + "<span style="color: darkred;"> : </span>" + linkStack.pop());<br /> }<br /> }</pre></div><br />以上代码单易懂,q里不做q多解释?img src ="http://www.aygfsteel.com/yongboy/aggbug/346222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yongboy/" target="_blank">nieyong</a> 2010-10-05 11:36 <a href="http://www.aygfsteel.com/yongboy/archive/2010/10/05/346222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java war 打包、解压命?/title><link>http://www.aygfsteel.com/yongboy/archive/2009/09/04/293900.html</link><dc:creator>nieyong</dc:creator><author>nieyong</author><pubDate>Fri, 04 Sep 2009 08:39:00 GMT</pubDate><guid>http://www.aygfsteel.com/yongboy/archive/2009/09/04/293900.html</guid><wfw:comment>http://www.aygfsteel.com/yongboy/comments/293900.html</wfw:comment><comments>http://www.aygfsteel.com/yongboy/archive/2009/09/04/293900.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yongboy/comments/commentRss/293900.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yongboy/services/trackbacks/293900.html</trackback:ping><description><![CDATA[<p>l常工E打包成war包,打包如下Q?/p> <p>// 当前目录打包成war?/p> <p>jar   cvf   temp.war   */  . </p> <p>命o(h)格式Q?/p> <p>java cvf 打包文g名称 要打包的目录 打包文g保存路径</p> <p> </p> <p>解压自然是:</p> <p>jar xvf temp.war</p> <p> </p> <p>jar和linux下面的tar命o(h)cM</p><img src ="http://www.aygfsteel.com/yongboy/aggbug/293900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yongboy/" target="_blank">nieyong</a> 2009-09-04 16:39 <a href="http://www.aygfsteel.com/yongboy/archive/2009/09/04/293900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ĵ</a>| <a href="http://" target="_blank">Ȫ</a>| <a href="http://" target="_blank">ľ</a>| <a href="http://" target="_blank">Ӽ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">봨</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʯ</a>| <a href="http://" target="_blank">֣</a>| <a href="http://" target="_blank">ǰ</a>| <a href="http://" target="_blank">״</a>| <a href="http://" target="_blank">ͷ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʷ</a>| <a href="http://" target="_blank">Ҿ</a>| <a href="http://" target="_blank">Ӣɳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ȷ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">³</a>| <a href="http://" target="_blank">书</a>| <a href="http://" target="_blank">廪</a>| <a href="http://" target="_blank">̶</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ף</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʼ</a>| <a href="http://" target="_blank">ԭ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͨ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">γ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>