关于异步队列的学习
来源:互联网 发布: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;
}
}
}
}
结果:
- 关于异步队列的学习
- 关于GCD 队列,同步异步的理解
- nmq异步消息队列学习
- 关于GCD中串行队列、并发队列和同步执行、异步执行的探讨
- JS 异步队列的实现
- 关于事件驱动的学习一 异步IO aio
- 关于廖雪峰yield,协程,异步的一些学习记录
- IOS关于异步请求学习
- 关于异步的思考
- 关于异步的理解
- 关于异步的思考
- 关于异步的理解
- 队列、优先队列的学习
- iOS 关于队列线程和后台异步运行程序
- 队列方式的异步写入数据模式
- POSIX消息队列的异步通信机制
- 自己写的异步多线程队列
- 一个C++异步队列的测试程序
- plist文件的写入和读取
- Unity Shader内置矩阵
- leetcode Number of Islands
- 分布式架构、大数据、机器学习、搜索、推荐、广告
- 周记——20151207
- 关于异步队列的学习
- php 文件操作,PHP ZipArchive扩展库,php处理flash扩展
- JSP页面中引入js文件
- ubuntu unrar解压rar包和unzip 解压zip包
- Django Ckeditor Ueditor 内容 展示 显示 HTML 显示不正常问题
- linux mount (挂载命令)详解
- 8-《电子入门趣谈》第一章_一切从单片机开始-1.3.5定时器/计数器
- Restful API的设计与实践
- android之HttpURLConnection