1. 程式人生 > >【佇列 高併發】java web瞬間高併發的解決方法

【佇列 高併發】java web瞬間高併發的解決方法

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 {
            //佇列不正常,或佇列大小已達上限,做出相應處理

        }

    }
}

好了,這時候,利用過濾器或者攔截器將每個請求封裝成佇列元素進行處理就行。

當然了,對於多應用伺服器的部署架構來說,資料庫也需要加鎖,資料庫隔離級別另說。

相關推薦

佇列 併發java web瞬間併發解決方法

1、任何的高併發,請求總是會有一個順序的 2、java的佇列的資料結構是先進先出的取值順序 3、BlockingQueue類(執行緒安全)(使用方法可以百度) 一般使用LinkedBlockingQueue 利用以上幾點,我們可以把高併發時候的請求放入一個佇列,佇

個人學習筆記Java Web用一個簡單的jsp頁面實現輸出100以內的素數

<%@ page language="java" import="java.util.*" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%> <html> <

markdown編輯器插入圖片無法顯示的解決方法以及段首縮排

markdown編輯器插入圖片無法顯示 任意markdown編輯器下插入圖片無法顯示 大家有麼有遇見過這樣的現象,在我給段落進行縮排時,預覽區出現了這樣的情況: 大薩達大薩達阿斯頓的薩達的阿斯頓愛的阿斯達使得阿斯達實打實的大多數薩達愛上

SQL Server 2008評估期已過的解決方法

前言:      開啟資料庫後,突然彈出來一個對話方塊: 解決:      出現這個問題是因為SQL Server 2008沒有啟用,啟用方法如下:      1.找到SQL Server 的安裝中

程式設計架構實戰——Java併發包基石-AQS詳解

目錄 1 基本實現原理 1.1 如何使用 1.2 設計思想 2 自定義同步器 2.1 同步器程式碼實現 2.2 同步器程式碼測試 3 原始碼分析 3.1 Node結點 3.2 獨佔式 3.3 共享式 4 總結   Java併發包(JUC)中提供了很多

JAVAJava Web 介紹

Web 概念: 表示Internet主機上供外界訪問的資源。 Internet上供外界訪問的Web資源分為: 靜態web資源(Static Web): 指web頁面中供人們瀏覽的資料始終是不變。 靜態技術有:HTML; 靜態資源有:** .

Java併發Java中的原子操作

Java中的原子操作 原子更新基本型別 原子更新陣列 原子更新引用型別 原子更新欄位類 參考 原子更新基本型別 一個生動的例子 public class AtomicIntegerExample { privat

Java併發Java中的執行緒池

Java中的執行緒池 執行流程 執行緒池的建立 提交任務 關閉執行緒池 參考 執行流程 處理流程如下: execute()方法執行示意圖如下: 執行緒池的建立 corePoolSize:執行緒池

第22天Java執行緒基礎、併發集合

1 概述 2 生命週期(五狀態圖) 3 如何定義一個執行緒 4 控制執行緒執行的方法 1 概述        程式當中一條獨立的執行線索。Java中的主執行緒是一個J

死磕Java併發-----Java記憶體模型之happens-before

在上篇部落格(【死磕Java併發】—–深入分析volatile的實現原理)LZ提到過由於存線上程本地記憶體和主記憶體的原因,再加上重排序,會導致多執行緒環境下存在可見性的問題。那麼我們正確使用同步、鎖的情況下,執行緒A修改了變數a何時對執行緒B可見? 我們無法就所有場景來規

簡記Java Web 內幕——Spring原始碼(元件分析,BeanFactory原始碼,Bean建立之前)

本章內容: Bean元件、Context元件解析 BeanFactory的建立 初始化Bean例項之前的操作 Bean元件解析 Spring Bean 的建立是典型的工廠模式, 它的頂級介面是BeanFactory。 Bean工廠的類層次關係

乾貨合集大流量與併發:資料庫、架構與實踐技巧

2016年9月20-21日20:00-21:30,淘寶開放平臺與阿里云云棲社群將聯合舉辦“大流量高併發網際網路應用實踐線上峰會”,為廣大開發者分享阿里的海量使用者支撐及運營經驗。 報名入口:http://yq.aliyun.com/webinar/join/49?spm=5176.8155509.4376

死磕Java併發-----Java記憶體模型之分析volatile

volatile可見性;對一個volatile的讀,總可以看到對這個變數最終的寫; volatile原子性;volatile對單個讀/寫具有原子性(32位Long、Double),但是複合操作除外,例如i++; JVM底層採用“記憶體屏障”來實現volat

死磕Java併發—– J.U.C之併發工具類:Semaphore

此篇部落格所有原始碼均來自JDK 1.8訊號量Semaphore是一個控制訪問多個共享資源的計數

死磕Java併發--Java記憶體模型之happens-before

在上篇部落格(【死磕Java併發】—–深入分析volatile的實現原理)LZ提到過由於存線上程本地記憶體和主記憶體的原因,再加上重排序,會導致多執行緒環境下存在可見性的問題。那麼我們正確使用同步、鎖的情況下,執行緒A修改了變數a何時對執行緒B可見?我們無法就所有場景來規定某

死磕Java併發-----Java記憶體模型之總結

經過四篇部落格闡述,我相信各位對Java記憶體模型有了最基本認識了,下面LZ就做一個比較簡單的總結。 總結 JMM規定了執行緒的工作記憶體和主記憶體的互動關係,以及執行緒之間的可見性和程式的執行順序。一方面,要為程式設計師提供足夠強的記憶體可見性保證;另

Java—— java Web 啟動時自動執行程式碼的幾種方式(總有些程式碼需要在虛擬機器啟動時執行)

Web容器啟動後執行程式碼的幾種方式其執行順序為:4===>5===>1===>2===>3即指定init-method的Bean開始執行接著實現Spring的Bean後置處理器開始執行然後是Servlet的監聽器執行再接下來是Servlet的過濾器執

死磕Java併發-----J.U.C之併發工具類:Exchanger

此篇部落格所有原始碼均來自JDK 1.8 前面三篇部落格分別介紹了CyclicBarrier、CountDownLatch、Semaphore,現在介紹併發工具類中的最後一個Exchange。Exchange是最簡單的也是最複雜的,簡單在於API非常簡

java web開發 併發處理

java處理高併發高負載類網站中資料庫的設計方法(java教程,java處理大量資料,java高負載資料)  一:高併發高負載類網站關注點之資料庫  沒錯,首先是資料庫,這是大多數應用所面臨的首個SPOF。尤其是Web2.0的應用,資料庫的響應是首先要解決的。 一般來說MySQL是最常用的,可能最初是一個m

死磕Java併發-----J.U.C之併發工具類:CyclicBarrier

此篇部落格所有原始碼均來自JDK 1.8 CyclicBarrier,一個同步輔助類,在API中是這麼介紹的: 它允許一組執行緒互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的執行緒的程式中,這些執