多线程设计模式(一)
DelayQueue的使用设计
我们谈一下实际的场景吧。我们在开发中,有如下场景
a) 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
b) 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
c) 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求。
今天我们举个简单的例子来设计一下DelayQueue的用法,这种具有设计意义的代码,非常的通用,只要思路够开通,很多业务场景能都使用。我们都会去网吧上网,假如这个网吧有三台机器,网费是一秒钟,三个人同时上网,如果时间到了自动下机,我们该如何设计?我们如果知道DelayQueue的话,这个问题就变得非常简单了,无非是所有的上网者全部放到一个队列中,如果过期了则从队列中移除。话不多说,直接上代码。
收线我们先设计上网者的类:
1 public class Wangmin implements Delayed { 2 3 private String name; 4 //身份证 5 private String id; 6 //截止时间 7 private long endTime; 8 //定义时间工具类 9 private TimeUnit timeUnit = TimeUnit.SECONDS; 10 11 public Wangmin(String name,String id,long endTime){ 12 this.name=name; 13 this.id=id; 14 this.endTime = endTime; 15 } 16 17 public String getName(){ 18 return this.name; 19 } 20 21 public String getId(){ 22 return this.id; 23 } 24 25 /** 26 * 用来判断是否到了截止时间 27 */ 28 @Override 29 public long getDelay(TimeUnit unit) { 30 //return unit.convert(endTime, TimeUnit.MILLISECONDS) - unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS); 31 return endTime - System.currentTimeMillis(); 32 } 33 34 /** 35 * 相互批较排序用 36 */ 37 @Override 38 public int compareTo(Delayed delayed) { 39 Wangmin w = (Wangmin)delayed; 40 return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) > 0 ? 1:0; 41 } 42 43 }
这里需要指出的是,必须要实现Delayed接口。
网吧的类,实现Runnable接口
1 public class WangBa implements Runnable { 2 3 private DelayQueue<Wangmin> queue = new DelayQueue<Wangmin>(); 4 5 public boolean yinye =true; 6 7 public void shangji(String name,String id,int money){ 8 Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis()); 9 System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"交钱"+money+"块,开始上机..."); 10 this.queue.add(man); 11 } 12 13 public void xiaji(Wangmin man){ 14 System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"时间到下机..."); 15 } 16 17 @Override 18 public void run() { 19 while(yinye){ 20 try { 21 Wangmin man = queue.take(); 22 xiaji(man); 23 } catch (InterruptedException e) { 24 e.printStackTrace(); 25 } 26 } 27 } 28 29 public static void main(String args[]){ 30 try{ 31 System.out.println("网吧开始营业"); 32 WangBa siyu = new WangBa(); 33 Thread shangwang = new Thread(siyu); 34 shangwang.start(); 35 36 siyu.shangji("路人甲", "123", 1); 37 siyu.shangji("路人乙", "234", 10); 38 siyu.shangji("路人丙", "345", 5); 39 } 40 catch(Exception e){ 41 e.printStackTrace(); 42 } 43 44 } 45 }
运行程序,输出如下:
1 网吧开始营业 2 网名路人甲 身份证123交钱1块,开始上机... 3 网名路人乙 身份证234交钱10块,开始上机... 4 网名路人丙 身份证345交钱5块,开始上机... 5 网名路人甲 身份证123时间到下机... 6 网名路人丙 身份证345时间到下机... 7 网名路人乙 身份证234时间到下机...
134的网名一秒钟之后下机,345的网民五秒钟之后下机,234的网民十秒钟下机。执行完成后,程序依然不会停止,因为while循环没有结束,也就是说网吧依旧还在营业,我们只是模拟一个场景,我们在实际的业务中可以提供接口去让网吧停止营业。还是那句话,只要自己善于思考,可以总结出非常多的适合自己业务的一些设计方法,并不需要仅仅局限于Java的设计模式,源于前人的标准,而又有自己的特色。