关于异步队列的学习
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;
}
}
}
}
结果:
有关异步机制和同步机制的基础知识请参考其他同学的文章: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;
}
}
}
}
结果:
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python3写爬虫(四)多线程实现数据爬取
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树