一段簡單程式碼理解非同步請求訊息佇列在高併發環境中的作用

爆裂碼手發表於2017-08-29

普通同步方法被呼叫模擬

package top.yuyufeng.mq;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * Created by yuyufeng on 2017/8/29.
 */
public class MyServer {
    private static AtomicInteger atomicInteger = new AtomicInteger(1);

    public static void createOrder(String product) {
        int res = atomicInteger.getAndIncrement();
        if (res >= 10) {
            System.err.println("超過當前容量(10) " + res);
        }
        System.out.println(product + "當前正在處理的執行緒數 " + res);
        doJob();
        atomicInteger.getAndDecrement();
    }

    private static void doJob() {
        Random random = new Random();
        long sleepTime = random.nextInt(10) * 100;
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //模擬發起請求  併發一旦上去,就會超過限制大小,有當機危險
        for (int i = 0; i < 12; i++) {
            new Thread() {
                @Override
                public void run() {
                    for (int j = 0; j < 10; j++) {
                        MyServer.createOrder(Thread.currentThread().getName());
                    }
                    System.out.println(Thread.currentThread().getName() + "結束:" + atomicInteger);

                }
            }.start();
        }
    }
}

執行這段程式碼之後,你會看到,併發一單上去,當前處理的程式會超過額定容量(這裡設定為最高能應對10個程式同時處理,超過會卡頓)

應用訊息佇列後,變成非同步請求

package top.yuyufeng.mq;

import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by yuyufeng on 2017/8/29.
 */
public class MyServerByQuene {
    private static AtomicInteger atomicInteger = new AtomicInteger();
    //這裡使用jdk佇列,代替常用的訊息佇列服務
    private static Queue<String> queue = new ConcurrentLinkedQueue<>();
    private static ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(10);

    public static void createOrder(String product) {
        queue.add(product);
    }

    static {
        //10個程式阻塞處理請求
        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        String product = queue.poll();
                        if (product != null) {
                            int res = atomicInteger.getAndIncrement();
                            if (res >= 10) {
                                System.err.println("超過當前容量(10) " + res);
                            }
                            System.out.println(product + "當前正在處理的執行緒數 " + res);
                            doJob();
                            atomicInteger.getAndDecrement();
                        } else {
                            try {
                                Thread.sleep(1000);
                                System.out.println("MyServerByQuene.run 正在監聽...當前程式數量: " + atomicInteger);
                            } catch (InterruptedException e) {
                            }
                        }

                    }
                }
            });
        }

    }


    private static void doJob() {
        Random random = new Random();
        long sleepTime = random.nextInt(10) * 100;
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //模擬發起請求,這裡的併發更大 ,但是是非同步訊息佇列,會等待處理.能抗住高併發
        for (int i = 0; i < 20; i++) {
            new Thread() {
                @Override
                public void run() {
                    for (int j = 0; j < 10; j++) {
                        MyServerByQuene.createOrder(Thread.currentThread().getName() + j);
                    }
                    System.out.println(Thread.currentThread().getName() + "結束:" + atomicInteger);

                }
            }.start();
        }


    }
}

執行之後,你會發現,無論多少個執行緒去請求,總的正在處理執行緒的數量不會變.

這就是訊息佇列,非同步請求在高併發環境下所起的作用

相關文章