关于异步队列的学习

来源:互联网 发布:golang 编辑:程序博客网 时间:2024/06/05 09:28

Ps:第一次在网上写文章,如有错误之处,还请指教。谢谢。

有关异步机制和同步机制的基础知识请参考其他同学的文章:http://blog.itpub.net/17074730/viewspace-563262/

最近有在学习多线程的知识,以前这方面由于涉及的少,所以每次碰到都没怎么去关注,这样就更加无法去解决问题了。最近出去面了几家公司,发现所问的问题都差不多(只是深浅不一而已),其中像分布式、设计模式、多线程、设计模式、负载均衡这些知识点都是有问到的。好了,废话不多说,直接贴源码了。

问题使用场景:(朋友公司的业务)手机号码发送验证码,但是每个手机号码每天只能发送三次。

前期设计:采用MAP做静态缓存,每天定时清除MAP。对于MAP的计算判定方法用synchronized修饰确保线程安全。可是经测试发现,验证10W个手机号码的运行时间竟然在30秒左右,这性能太LOW了。正好,我在学习这方面,所以就尝试着用异步队列实现了下功能,经测试,10W级别的数据大概在3-4秒左右。不得感叹着玩意确实强大。

代码如下:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;


interface SendCheckCodeDao{
    
    /**
     * 发送验证码
     */
    public boolean sendCode(String telphone);
}
public class SendCheckCodeDaoImpl implements SendCheckCodeDao{

    public static void main(String[] args) throws InterruptedException {
        init(); //如果是spring的话可以设置在bean的init里面,注意这个只要启动一次即可。以后会一直等待队列的添加.
        long start = System.currentTimeMillis();
        for(int i = 0 ; i < 100000 ; i++){
            SendCheckCodeDao dao = new SendCheckCodeDaoImpl();
            boolean result = dao.sendCode(5+"");
            if(result){
                System.out.println("true");
            }
        }
        System.out.println("end========================="+(System.currentTimeMillis()-start));
    }
    
    
    
    /**
     * 发送验证码并且验证  ----对外接口
     */
    @Override
    public boolean sendCode(String telphone) {
        boolean checkResult = CheckTelphoneNumer.checkCode(telphone);
        if(!checkResult){
            return Boolean.FALSE;
        }else{
            TelPhoneQueue.add(telphone);
            return Boolean.TRUE;
        }
    }
    
    private static void init(){
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    BlockingQueue<String> queue = TelPhoneQueue.getQueue();
                    synchronized (queue) {
                        while(queue.isEmpty()){ //
                            try {
                                System.out.println("队列  wait...");
                                queue.wait(); //队列为空时,使线程处于等待状态
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        String tel = TelPhoneQueue.get(); //得到第一个
                        System.out.println(tel);    //需替换成实际发送验证码的接口调用,这里用打印手机号代替
                    }
                }
            }
        }).start();
    }
    
 }
    
    class CheckTelphoneNumer{ 
        
        public static ConcurrentMap<String,Integer> currentMap = new ConcurrentHashMap<String, Integer>();
        
        private static final int MAX_SEND_COUNT = 3;
        /**
         * 验证当前手机号码是否 -- 
         * 
         * @param telphone
         */
        public static  boolean checkCode(String telphone){
            synchronized(CheckTelphoneNumer.currentMap){
                if(telphone == null || "".equals(telphone)){
                    return false;
                }
                StringBuffer key = new StringBuffer(telphone).append(getDateByStr());
                if(currentMap.containsKey(key.toString())){ //表示包含
                    int count  = currentMap.get(key.toString()).intValue()+1;
                    if(count > MAX_SEND_COUNT){
                        return false;
                    }else{
                        currentMap.put(key.toString(), new Integer(count));
                    }
                }else{
                    currentMap.put(key.toString(), new Integer(1));
                }
                return true;
            }
        }
        
        /**
         * 这个也一样
         * @return
         */
        private static  String getDateByStr(){
            SimpleDateFormat formatter =   new SimpleDateFormat( "yyyyMMdd" );
            Date date = new Date();
            return formatter.format(date);
        }
        
        public static  void clearPhone(){
            synchronized(CheckTelphoneNumer.currentMap){
                currentMap.clear();
            }
        }


    }


class TelPhoneQueue{
    private static BlockingQueue<String> queue = new LinkedBlockingQueue<String>(); 
    
    public static BlockingQueue<String> getQueue() {
        return queue;
    }


    public static boolean add(String telPhone){
        synchronized(queue){
            try {
                queue.put(telPhone);
                queue.notifyAll();//激活该队列对应的全部线程
                return true;
            } catch (InterruptedException e) {
                return false;
                //logger.error("", e);
            }
        }
    }
    
    public static String get(){
        synchronized(queue){
            //从队列中获取需要处理的手机号码,最长等待时间为2秒,取不到返回空
            try {
                return (String)queue.poll(2 , TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                //logger.error("", e);
                return null;
            }
        }
    }
    
}


结果:

      


0 0
原创粉丝点击