您的位置:首页 > 编程语言 > Java开发

关于异步队列的学习

2015-12-08 09:44 405 查看
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)){

 
9277
                  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;

            }

        }

    }

    

}


结果:

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息