多线程设计模式(一)

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的设计模式,源于前人的标准,而又有自己的特色。

原文地址:https://www.cnblogs.com/yujiwei/p/7455559.html