java web如何解决瞬间高并发
程序员文章站
2024-03-04 16:15:11
1、任何的高并发,请求总是会有一个顺序的
2、java的队列的数据结构是先进先出的取值顺序
3、blockingqueue类(线程安全)(使用方法可以百度)
一般...
1、任何的高并发,请求总是会有一个顺序的
2、java的队列的数据结构是先进先出的取值顺序
3、blockingqueue类(线程安全)(使用方法可以百度)
一般使用linkedblockingqueue
利用以上几点,我们可以把高并发时候的请求放入一个队列,队列的大小可以自己定义,比如队列容量为1000个数据,那么可以利用过滤器或者拦截器把当前的请求放入队列,如果队列的容量满了,其余的请求可以丢掉或者作出相应回复
具体实施:
利用生产者、消费者模型:
将队列的请求一一处理完。
上代码:
/** * @author fuguangli * @description 前沿消费者类 * @create date: 2017/3/7 * @using example */ public class customer implements runnable{ /** * 抛出异常 特殊值 阻塞 超时 插入 add(e) offer(e) put(e) offer(e, time, unit) 移除 remove() poll() take() poll(time, unit) 检查 element() peek() 不可用 不可用 */ private blockingqueue blockingqueue; private atomicinteger count = new atomicinteger(); public customer(blockingqueue blockingqueue) { this.blockingqueue = blockingqueue; } /** * when an object implementing interface <code>runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p/> * the general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see thread#run() */ @override public void run() { system.out.println("消费者线程启动..."); lockflag.setcustomerrunningflag(true); try { while (lockflag.getproducerrunningflag()){ system.out.println(thread.currentthread().getid()+"i'm customer.queue current size="+blockingqueue.size()); string data = (string) blockingqueue.poll(10, timeunit.seconds); if(data!=null){ system.out.println(thread.currentthread().getid()+"*************正在消费数据 data="+data); }else{ //表示超过取值时间,视为生产者不再生产数据 system.out.println(thread.currentthread().getid()+"队列为空无数据,请检查生产者是否阻塞"); } thread.sleep(50); } system.err.println("消费者程序执行完毕"); } catch (interruptedexception e) { e.printstacktrace(); system.err.println("消费者程序退出"); lockflag.setcustomerrunningflag(false);//异常退出线程 thread.currentthread().interrupt(); } } }
package com.qysxy.framework.queue; import java.util.concurrent.blockingqueue; import java.util.concurrent.timeunit; import java.util.concurrent.atomic.atomicinteger; /** * @author fuguangli * @description 队列生产者类 * @create date: 2017/3/7 * @using example */ public class producer implements runnable{ /** * 抛出异常 特殊值 阻塞 超时 插入 add(e) offer(e) put(e) offer(e, time, unit) 移除 remove() poll() take() poll(time, unit) 检查 element() peek() 不可用 不可用 */ private blockingqueue blockingqueue; private atomicinteger count = new atomicinteger(); public producer(blockingqueue blockingqueue) { this.blockingqueue = blockingqueue; } /** * when an object implementing interface <code>runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p/> * the general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see thread#run() */ @override public void run() { system.out.println("生产者线程启动..."); lockflag.setproducerrunningflag(true); try { while (lockflag.getproducerrunningflag()){ string data = "data:"+count.incrementandget(); if(blockingqueue.offer(data,10, timeunit.seconds)){ //返回true表示生产数据正确 system.out.println("^^^^^^^^^^^^^^正在生产数据 data="+data); }else { //表示阻塞时间内还没有生产者生产数据 system.out.println("生产者异常,无法生产数据"); } thread.sleep(50); } } catch (interruptedexception e) { e.printstacktrace(); system.err.println("生产者程序退出"); lockflag.setproducerrunningflag(false);//异常退出线程 thread.currentthread().interrupt(); } } }
package com.qysxy.framework.queue; /** * @author fuguangli * @description 前沿生产者消费者模型的锁类 * @create date: 2017/3/7 */ public class lockflag { /** * 生产者互斥锁 */ private static boolean producerrunningflag = false; /** * 消费者互斥锁 */ private static boolean customerrunningflag = false; public static boolean getproducerrunningflag() { return producerrunningflag; } public static void setproducerrunningflag(boolean producerrunningflag) { lockflag.producerrunningflag = producerrunningflag; } public static boolean getcustomerrunningflag() { return customerrunningflag; } public static void setcustomerrunningflag(boolean customerrunningflag) { lockflag.customerrunningflag = customerrunningflag; } }
package com.qysxy.framework.queue; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.util.queue; import java.util.concurrent.*; /** * @author fuguangli * @description 前沿队列实用类,用于大量并发用户 * @create date: 2017/3/7 */ public class blockingqueuehelper { private static final integer maxqueuesize = 1000; private static blockingqueue blockingqueue = new linkedblockingqueue(maxqueuesize); private static executorservice threadpool = executors.newcachedthreadpool(); public static blockingqueue getblockingqueue() { if (blockingqueue == null) { blockingqueue = new linkedblockingqueue(maxqueuesize); } return blockingqueue; } /** * @param o 队列处理对象(包含request,response,data) */ public static void requestqueue(object o) { //检测当前的队列大小 if (blockingqueue != null && blockingqueue.size() < maxqueuesize) { //可以正常进入队列 if (blockingqueue.offer(o)) { //添加成功,检测数据处理线程是否正常 if (lockflag.getcustomerrunningflag()) { //说明处理线程类正常运行 } else { //说明处理线程类停止,此时,应重新启动线程进行数据处理 lockflag.setcustomerrunningflag(true); //example:run customer customer = new customer(blockingqueue); threadpool.execute(customer); } } else { //进入队列失败,做出相应的处理,或者尝试重新进入队列 } } else { //队列不正常,或队列大小已达上限,做出相应处理 } } }
好了,这时候,利用过滤器或者拦截器将每个请求封装成队列元素进行处理就行。
当然了,对于多应用服务器的部署架构来说,数据库也需要加锁,数据库隔离级别下篇再说。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。