zoukankan      html  css  js  c++  java
  • java web解决瞬间高并发的策略

    1、任何的高并发,请求总是会有一个顺序的

    2、java的队列的数据结构是先进先出的取值顺序

    3、BlockingQueue类(线程安全)(使用方法可以百度)

    一般使用LinkedBlockingQueue

    利用以上几点,我们可以把高并发时候的请求放入一个队列,队列的大小可以自己定义,比如队列容量为1000个数据,那么可以利用过滤器或者拦截器把当前的请求放入队列,如果队列的容量满了,其余的请求可以丢掉或者作出相应回复

    具体实施:

    利用生产者、消费者模型:

    将队列的请求一一处理完。

    上代码:

     1 /**
     2  * @author fuguangli
     3  * @description 前沿消费者类
     4  * @Create date:    2017/3/7
     5  * @using   EXAMPLE
     6  */
     7 public class Customer implements Runnable{
     8 
     9 
    10     /**
    11      *         抛出异常    特殊值        阻塞         超时
    12      插入    add(e)    offer(e)    put(e)    offer(e, time, unit)
    13      移除    remove()    poll()    take()    poll(time, unit)
    14      检查    element()    peek()    不可用    不可用
    15 
    16      */
    17     private BlockingQueue blockingQueue;
    18     private AtomicInteger count = new AtomicInteger();
    19     public Customer(BlockingQueue blockingQueue) {
    20         this.blockingQueue = blockingQueue;
    21     }
    22 
    23     /**
    24      * When an object implementing interface <code>Runnable</code> is used
    25      * to create a thread, starting the thread causes the object's
    26      * <code>run</code> method to be called in that separately executing
    27      * thread.
    28      * <p/>
    29      * The general contract of the method <code>run</code> is that it may
    30      * take any action whatsoever.
    31      *
    32      * @see Thread#run()
    33      */
    34     @Override
    35     public void run() {
    36         System.out.println("消费者线程启动...");
    37         LockFlag.setCustomerRunningFlag(true);
    38         try {
    39             while (LockFlag.getProducerRunningFlag()){
    40                 System.out.println(Thread.currentThread().getId()+"I'm Customer.Queue current size="+blockingQueue.size());
    41                 String data = (String) blockingQueue.poll(10, TimeUnit.SECONDS);
    42                 if(data!=null){
    43                     System.out.println(Thread.currentThread().getId()+"*************正在消费数据 data="+data);
    44                 }else{
    45                     //表示超过取值时间,视为生产者不再生产数据
    46                     System.out.println(Thread.currentThread().getId()+"队列为空无数据,请检查生产者是否阻塞");
    47                 }
    48                 Thread.sleep(50);
    49             }
    50             System.err.println("消费者程序执行完毕");
    51         } catch (InterruptedException e) {
    52             e.printStackTrace();
    53             System.err.println("消费者程序退出");
    54             LockFlag.setCustomerRunningFlag(false);//异常退出线程
    55             Thread.currentThread().interrupt();
    56         }
    57     }
    58 }
     1 package com.qysxy.framework.queue;
     2 
     3 import java.util.concurrent.BlockingQueue;
     4 import java.util.concurrent.TimeUnit;
     5 import java.util.concurrent.atomic.AtomicInteger;
     6 
     7 /**
     8  * @author fuguangli
     9  * @description 队列生产者类
    10  * @Create date:    2017/3/7
    11  * @using       EXAMPLE
    12  */
    13 public class Producer implements Runnable{
    14 
    15 
    16     /**
    17      *         抛出异常    特殊值        阻塞         超时
    18      插入    add(e)    offer(e)    put(e)    offer(e, time, unit)
    19      移除    remove()    poll()    take()    poll(time, unit)
    20      检查    element()    peek()    不可用    不可用
    21 
    22      */
    23     private BlockingQueue blockingQueue;
    24     private AtomicInteger count = new AtomicInteger();
    25     public Producer(BlockingQueue blockingQueue) {
    26         this.blockingQueue = blockingQueue;
    27     }
    28 
    29     /**
    30      * When an object implementing interface <code>Runnable</code> is used
    31      * to create a thread, starting the thread causes the object's
    32      * <code>run</code> method to be called in that separately executing
    33      * thread.
    34      * <p/>
    35      * The general contract of the method <code>run</code> is that it may
    36      * take any action whatsoever.
    37      *
    38      * @see Thread#run()
    39      */
    40     @Override
    41     public void run() {
    42         System.out.println("生产者线程启动...");
    43         LockFlag.setProducerRunningFlag(true);
    44         try {
    45             while (LockFlag.getProducerRunningFlag()){
    46                 String data = "data:"+count.incrementAndGet();
    47                 if(blockingQueue.offer(data,10, TimeUnit.SECONDS)){
    48                     //返回true表示生产数据正确
    49                     System.out.println("^^^^^^^^^^^^^^正在生产数据 data="+data);
    50                 }else {
    51                     //表示阻塞时间内还没有生产者生产数据
    52                     System.out.println("生产者异常,无法生产数据");
    53                 }
    54                 Thread.sleep(50);
    55 
    56             }
    57         } catch (InterruptedException e) {
    58             e.printStackTrace();
    59             System.err.println("生产者程序退出");
    60             LockFlag.setProducerRunningFlag(false);//异常退出线程
    61             Thread.currentThread().interrupt();
    62         }
    63     }
    64 }
     1 package com.qysxy.framework.queue;
     2 
     3 /**
     4  * @author fuguangli
     5  * @description 前沿生产者消费者模型的锁类
     6  * @Create date:    2017/3/7
     7  */
     8 public class LockFlag {
     9     /**
    10      * 生产者互斥锁
    11      */
    12     private static Boolean producerRunningFlag = false;
    13     /**
    14      * 消费者互斥锁
    15      */
    16     private static Boolean customerRunningFlag = false;
    17 
    18     public static Boolean getProducerRunningFlag() {
    19         return producerRunningFlag;
    20     }
    21 
    22     public static void setProducerRunningFlag(Boolean producerRunningFlag) {
    23         LockFlag.producerRunningFlag = producerRunningFlag;
    24     }
    25 
    26     public static Boolean getCustomerRunningFlag() {
    27         return customerRunningFlag;
    28     }
    29 
    30     public static void setCustomerRunningFlag(Boolean customerRunningFlag) {
    31         LockFlag.customerRunningFlag = customerRunningFlag;
    32     }
    33 }
     1 package com.qysxy.framework.queue;
     2 
     3 import javax.servlet.http.HttpServletRequest;
     4 import javax.servlet.http.HttpServletResponse;
     5 import java.util.Queue;
     6 import java.util.concurrent.*;
     7 
     8 /**
     9  * @author fuguangli
    10  * @description 前沿队列实用类,用于大量并发用户
    11  * @Create date:    2017/3/7
    12  */
    13 public class BlockingQueueHelper {
    14 
    15 
    16     private static final Integer maxQueueSize = 1000;
    17     private static BlockingQueue blockingQueue = new LinkedBlockingQueue(maxQueueSize);
    18     private static ExecutorService threadPool = Executors.newCachedThreadPool();
    19 
    20 
    21     public static BlockingQueue getBlockingQueue() {
    22         if (blockingQueue == null) {
    23             blockingQueue = new LinkedBlockingQueue(maxQueueSize);
    24         }
    25         return blockingQueue;
    26     }
    27 
    28     /**
    29      * @param o 队列处理对象(包含request,response,data)
    30      */
    31     public static void requestQueue(Object o) {
    32         //检测当前的队列大小
    33         if (blockingQueue != null && blockingQueue.size() < maxQueueSize) {
    34             //可以正常进入队列
    35             if (blockingQueue.offer(o)) {
    36                 //添加成功,检测数据处理线程是否正常
    37                 if (LockFlag.getCustomerRunningFlag()) {
    38                     //说明处理线程类正常运行
    39                 } else {
    40                     //说明处理线程类停止,此时,应重新启动线程进行数据处理
    41                     LockFlag.setCustomerRunningFlag(true);
    42 
    43                     //example:run
    44                     Customer customer = new Customer(blockingQueue);
    45                     threadPool.execute(customer);
    46 
    47                 }
    48 
    49             } else {
    50                 //进入队列失败,做出相应的处理,或者尝试重新进入队列
    51 
    52             }
    53         } else {
    54             //队列不正常,或队列大小已达上限,做出相应处理
    55 
    56         }
    57 
    58     }
    59 }

    好了,这时候,利用过滤器或者拦截器将每个请求封装成队列元素进行处理就行。

    当然了,对于多应用服务器的部署架构来说,数据库也需要加锁,数据库隔离级别下篇再说。

  • 相关阅读:
    VS2010的新特性:3.新要害词 Dynamic
    VS2010的新特性:1.可选参数
    VS2010的新特性:4.简化了对 Office API 对象的访问
    VS2010的新特性:2.命实参数
    Not beside my body,but inside my heart!
    Tears...
    首乘“子弹头”列车
    What doesn't kill me makes me stronger!
    HongKong Business Trip
    胃部不适,原来好辛苦!
  • 原文地址:https://www.cnblogs.com/yuan951/p/6517810.html
Copyright © 2011-2022 走看看