自定义线程池管理器

  实现高并发控制

Posted by     mrcodesniper on September 23, 2017

前言

最近老是听起同学说服务端的高并发,那么移动端如果出现高并发我们又如何处理呢?抱着这样的疑问我模拟了一个高并发场景

模拟场景

for (int i=0;i<100;i++){//高并发
            final int finalI = i;
            Thread thread =new Thread(){
                @Override
                public void run() {
                    super.run();
                    Log.e("jjjjjj", "runnable---->"+ finalI);
                }
            };
            ThreadPoolManager.getInstance().execute(new FutureTask<Object>(thread,null),null);
        }


        Thread thread =new Thread(){
            @Override
            public void run() {
                super.run();
                Log.e("jjjjjj", "runnable---->finalIrunnable");
            }
        };
        //延迟10S放入队列
        ThreadPoolManager.getInstance().execute(new FutureTask<Object>(thread,null),(long)10000);//延时执行

上述在activity的代码 主要是循环创建101个线程并将线程交由线程管理器执行 最后的线程为延时线程 可以做一些收尾工作

自定义线程管理器

代码比较长 分析都在注解中

public class ThreadPoolManager {


    //静态内部类模式的单例
    private static class ThreadPoolManagerHolder{
        private static final ThreadPoolManager INSTANCE=new ThreadPoolManager();
    }
    private ThreadPoolManager(){//初始化创造自定义线程池执行器并从阻塞队列取任务执行
        //核心线程数4个,最大线程10个,空闲线程存活10s,线程任务缓冲队列4个线程量
        threadPoolExecutor=new ThreadPoolExecutor(4,10,10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),handler);
        threadPoolExecutor.execute(runnable);
    };

    public static ThreadPoolManager getInstance(){
        return ThreadPoolManagerHolder.INSTANCE;//静态内部类在调用此函数时才加载
    }


    private ThreadPoolExecutor threadPoolExecutor;//预定义线程执行器
    private LinkedBlockingQueue<Future<?>> service=new LinkedBlockingQueue<>();//阻塞队列

    private RejectedExecutionHandler handler=new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
            try {
                //被拒绝后重新排队
                service.put(new FutureTask<Object>(runnable,null));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    private Runnable runnable=new Runnable() {
        @Override
        public void run() {
            while (true) { //循环从阻塞队列拿线程执行
                FutureTask futureTask = null;
                try {
                    Log.e("myThreadPook","service size "+service.size());
                    futureTask = (FutureTask) service.take();
                    Log.e("myThreadPook","池  "+threadPoolExecutor.getPoolSize());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (futureTask != null) {
                    threadPoolExecutor.execute(futureTask);
                }
            }
        }
    };


    public <T> void  execute(final FutureTask<T> futureTask, Object delayed){
        if(futureTask!=null){
            try {
                if(delayed!=null){
                    Timer timer=new Timer();
                    timer.schedule(new TimerTask(){//延迟放入队列
                        public void run(){
                            try {
                                service.put(futureTask);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }},(long)delayed);
                }else {
                    service.put(futureTask);//直接放入队列
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果分析

04-11 02:49:34.480 11372-11414/com.example.mac.back E/myThreadPook: service size 100
04-11 02:49:34.480 11372-11414/com.example.mac.back E/myThreadPook: 池  1
04-11 02:49:34.485 11372-11414/com.example.mac.back E/myThreadPook: service size 99
04-11 02:49:34.485 11372-11414/com.example.mac.back E/myThreadPook: 池  2
04-11 02:49:34.506 11372-11414/com.example.mac.back E/myThreadPook: service size 98
04-11 02:49:34.506 11372-11414/com.example.mac.back E/myThreadPook: 池  3
04-11 02:49:34.509 11372-11414/com.example.mac.back E/myThreadPook: service size 97
04-11 02:49:34.509 11372-11414/com.example.mac.back E/myThreadPook: 池  4
04-11 02:49:34.509 11372-11414/com.example.mac.back E/myThreadPook: service size 96
04-11 02:49:34.509 11372-11414/com.example.mac.back E/myThreadPook: 池  4
04-11 02:49:34.510 11372-11414/com.example.mac.back E/myThreadPook: service size 95
04-11 02:49:34.510 11372-11414/com.example.mac.back E/myThreadPook: 池  4
04-11 02:49:34.510 11372-11414/com.example.mac.back E/myThreadPook: service size 94
04-11 02:49:34.510 11372-11414/com.example.mac.back E/myThreadPook: 池  4
04-11 02:49:34.510 11372-11414/com.example.mac.back E/myThreadPook: service size 93
04-11 02:49:34.510 11372-11414/com.example.mac.back E/myThreadPook: 池  4
04-11 02:49:34.533 11372-11415/com.example.mac.back E/jjjjjj: runnable---->0
04-11 02:49:34.533 11372-11415/com.example.mac.back E/jjjjjj: runnable---->3
04-11 02:49:34.533 11372-11415/com.example.mac.back E/jjjjjj: runnable---->4
04-11 02:49:34.533 11372-11415/com.example.mac.back E/jjjjjj: runnable---->5
04-11 02:49:34.533 11372-11415/com.example.mac.back E/jjjjjj: runnable---->6
04-11 02:49:34.550 11372-11414/com.example.mac.back E/myThreadPook: service size 92
04-11 02:49:34.550 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.551 11372-11417/com.example.mac.back E/jjjjjj: runnable---->1
04-11 02:49:34.551 11372-11418/com.example.mac.back E/jjjjjj: runnable---->2
04-11 02:49:34.567 11372-11414/com.example.mac.back E/myThreadPook: service size 91
04-11 02:49:34.567 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.567 11372-11414/com.example.mac.back E/myThreadPook: service size 90
04-11 02:49:34.567 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.567 11372-11414/com.example.mac.back E/myThreadPook: service size 89
04-11 02:49:34.568 11372-11415/com.example.mac.back E/jjjjjj: runnable---->9
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 88
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11415/com.example.mac.back E/jjjjjj: runnable---->10
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 87
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11415/com.example.mac.back E/jjjjjj: runnable---->11
04-11 02:49:34.568 11372-11415/com.example.mac.back E/jjjjjj: runnable---->12
04-11 02:49:34.568 11372-11417/com.example.mac.back E/jjjjjj: runnable---->13
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 86
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 85
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 84
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 83
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: service size 82
04-11 02:49:34.568 11372-11414/com.example.mac.back E/myThreadPook: 池  5
04-11 02:49:34.570 11372-11418/com.example.mac.back E/jjjjjj: runnable---->8
04-11 02:49:34.570 11372-11418/com.example.mac.back E/jjjjjj: runnable---->14
04-11 02:49:34.570 11372-11418/com.example.mac.back E/jjjjjj: runnable---->15
04-11 02:49:34.570 11372-11418/com.example.mac.back E/jjjjjj: runnable---->16
04-11 02:49:34.570 11372-11418/com.example.mac.back E/jjjjjj: runnable---->17
04-11 02:49:34.602 11372-11419/com.example.mac.back D/OpenGLRenderer: HWUI GL Pipeline
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: service size 81
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: 池  6
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: service size 80
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: 池  6
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: service size 79
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: 池  6
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: service size 78
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: 池  6
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: service size 77
04-11 02:49:34.607 11372-11414/com.example.mac.back E/myThreadPook: 池  6
04-11 02:49:34.608 11372-11418/com.example.mac.back E/jjjjjj: runnable---->19
04-11 02:49:34.608 11372-11418/com.example.mac.back E/jjjjjj: runnable---->20
04-11 02:49:34.608 11372-11418/com.example.mac.back E/jjjjjj: runnable---->21
04-11 02:49:34.608 11372-11418/com.example.mac.back E/jjjjjj: runnable---->22
04-11 02:49:34.621 11372-11420/com.example.mac.back E/jjjjjj: runnable---->7
04-11 02:49:34.654 11372-11414/com.example.mac.back E/myThreadPook: service size 76
....................................................................................
04-11 02:49:34.911 11372-11417/com.example.mac.back E/jjjjjj: runnable---->68
04-11 02:49:34.911 11372-11417/com.example.mac.back E/jjjjjj: runnable---->69
04-11 02:49:34.912 11372-11417/com.example.mac.back E/jjjjjj: runnable---->70
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: service size 29
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: service size 28
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: service size 27
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: service size 26
04-11 02:49:34.912 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:34.913 11372-11414/com.example.mac.back E/myThreadPook: service size 25
04-11 02:49:34.913 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:34.913 11372-11414/com.example.mac.back E/myThreadPook: service size 25
04-11 02:49:34.913 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:34.913 11372-11414/com.example.mac.back E/myThreadPook: service size 25
....................................................................................
04-11 02:49:34.961 11372-11414/com.example.mac.back E/myThreadPook: service size 0
04-11 02:49:34.963 11372-11417/com.example.mac.back E/jjjjjj: runnable---->82
04-11 02:49:34.964 11372-11421/com.example.mac.back E/jjjjjj: runnable---->87
04-11 02:49:34.968 11372-11426/com.example.mac.back E/jjjjjj: runnable---->67
04-11 02:49:44.495 11372-11414/com.example.mac.back E/myThreadPook: 池  10
04-11 02:49:44.501 11372-11415/com.example.mac.back E/jjjjjj: runnable---->finalIrunnable
04-11 02:49:44.501 11372-11414/com.example.mac.back E/myThreadPook: service size 0

首先在activity中将100个线程任务都加入阻塞队列中 然后线程执行器开始从阻塞队列中取任务 因为设置核心线程数为4 所以会在线程池中为任务创建新线程 直到为4 并将其他任务先加入到 线程执行器的缓冲队列中 这里我们设置了队列容量为4 已经完成了8个线程的分配

因为设置的最大线程数是10 当线程队列和缓冲队列都满时 线程池还会创建一个新线程 所以线程池中线程数量为5 并执行了5个任务  缓冲任务还剩3个任务 进入线程池运行 同时又有新线程 进入缓冲队列 这样进行 直到线程池线程和缓冲队列又满时 线程池 又会创建新线程 。。。直到线程池中线程个数为10

当线程池和缓冲队列都满时 会将阻塞队列的线程任务拒绝并重排 导致阻塞队列长度不变

最后我们可以看到阻塞队列的线程都已经执行完成 还有延迟任务也被成功执行

End.

Reference

ThreadPoolExecutor线程池解析与BlockingQueue的三种实现

android实现高性能,高并发,可延时线程池管理