zoukankan      html  css  js  c++  java
  • 阿里推荐的线程使用方法 ThreadPoolExecutor

    阿里推荐原因:使用线程池可以减少创建和销毁线程上所花的时间以及系统资源的开销,然后之所以不用Executors自定义线程池,用ThreadPoolExecutor是为了规范线程池的使用,还有让其他人更好懂线程池的运行规则。

    先说一下关于线程的概念

    任务:线程需要执行的代码,也就是Runnable
    任务队列:线程满了,就任务就放入任务队列里等待,等其他任务在线程里执行完,这个线程就空出来了,任务队列就将最早来的未执行的任务放入线程执行。
    核心线程:线程池一直存在的线程
    最大线程数量:指的是线程池所容纳的最多的线程数量

    ThreadPoolExecutor(int corePoolSize,
                            int maximumPoolSize,
                            long keepAliveTime,
                            TimeUnit unit,
                            BlockingQueue<Runnable> workQueue) 

    第一个是核心线程数量,第二个是最大线程数量,第三个是非核心线程的闲置超时时间,超过这个时间就会被回收,第四个是线程池中的任务队列模式。

    我们主要讲这个任务队列模式

    1.LinkedBlockingDeque

    我先上一个例子代码,再来唠嗑

    public class MainActivity extends AppCompatActivity {
    
        Button button;
        ThreadPoolExecutor executor;
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName() + " run");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            button = (Button) findViewById(R.id.btn_record_video);
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    executor.execute(myRunnable);
                    executor.execute(myRunnable);
                    executor.execute(myRunnable);
                }
            });
    
    
            executor = new ThreadPoolExecutor(3, 6, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
    
    
        }
    }
    

    当我们点击一次按钮

    03-03 15:00:43.503 5292-5333/com.example.zth.seven I/System.out: pool-1-thread-1 run
    03-03 15:00:43.505 5292-5335/com.example.zth.seven I/System.out: pool-1-thread-3 run
    03-03 15:00:43.505 5292-5334/com.example.zth.seven I/System.out: pool-1-thread-2 run

    连续点击两次

    03-03 15:10:47.941 7114-7259/com.example.zth.seven I/System.out: pool-1-thread-1 run
    03-03 15:10:47.941 7114-7260/com.example.zth.seven I/System.out: pool-1-thread-2 run
    03-03 15:10:47.942 7114-7261/com.example.zth.seven I/System.out: pool-1-thread-3 run
    03-03 15:10:49.942 7114-7260/com.example.zth.seven I/System.out: pool-1-thread-2 run
    03-03 15:10:49.942 7114-7259/com.example.zth.seven I/System.out: pool-1-thread-1 run
    03-03 15:10:49.942 7114-7261/com.example.zth.seven I/System.out: pool-1-thread-3 run

    这个时候就可以看出虽然说是最大线程数量是6,但是只用核心线程,不创建新线程,如果核心线程用完了就在队列里等待,队列的大小没有限制(你可随便点,他反正后来都会执行)

    但是还没完这个LinkedBlockingDeque还可以设置队列数量,如果我把队列设置为2

            executor = new ThreadPoolExecutor(3, 6, 3,
                    TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(2));

    然后连续点击2两次

    03-03 15:19:39.851 8971-9013/com.example.zth.seven I/System.out: pool-1-thread-1 run
    03-03 15:19:39.851 8971-9014/com.example.zth.seven I/System.out: pool-1-thread-2 run
    03-03 15:19:39.851 8971-9015/com.example.zth.seven I/System.out: pool-1-thread-3 run
    03-03 15:19:40.045 8971-9016/com.example.zth.seven I/System.out: pool-1-thread-4 run
    03-03 15:19:41.851 8971-9013/com.example.zth.seven I/System.out: pool-1-thread-1 run
    03-03 15:19:41.851 8971-9015/com.example.zth.seven I/System.out: pool-1-thread-3 run

    他这个时候能够创建四个线程了,为何,首先第一次点击占了三个核心线程,然后第二次点击将前两次任务放入队列里,然后队列满了就创建一个新线程用来执行最后一个任务

    如果我们连续点击三次,程序在我们点击第三次就崩溃了,因为线程数量超出最大线程数量了

    总结:LinkedBlockingDeque就首先使用核心线程,核心线程用完了就把任务放入队列里等待,如果队列满了就创建新线程,注意不设置队列数量,他就默认无限大。


    2.SynchronousQueue


    我们还是和以前一样换掉一行代码

            executor = new ThreadPoolExecutor(3, 6, 3,
                    TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

    点击一次

    03-03 15:39:31.915 12403-12446/com.example.zth.seven I/System.out: pool-1-thread-2 run
    03-03 15:39:31.915 12403-12447/com.example.zth.seven I/System.out: pool-1-thread-3 run
    03-03 15:39:31.915 12403-12445/com.example.zth.seven I/System.out: pool-1-thread-1 run

    连续点击两次

    03-03 15:39:53.204 12403-12446/com.example.zth.seven I/System.out: pool-1-thread-2 run
    03-03 15:39:53.204 12403-12445/com.example.zth.seven I/System.out: pool-1-thread-1 run
    03-03 15:39:53.204 12403-12447/com.example.zth.seven I/System.out: pool-1-thread-3 run
    03-03 15:39:53.371 12403-12501/com.example.zth.seven I/System.out: pool-1-thread-5 run
    03-03 15:39:53.371 12403-12502/com.example.zth.seven I/System.out: pool-1-thread-6 run
    03-03 15:39:53.371 12403-12500/com.example.zth.seven I/System.out: pool-1-thread-4 run

    可以看出来当核心线程占满时他没有将任务放入队列里去等待,而是直接创建新线程取执行任务

    连续点击三次

    程序崩溃,因为他创建的线程超过了最大线程数量,

    总结:SynchronousQueue很单纯,不使用队列,核心线程用完了就创建新线程,

     

    参考文章:

    http://blog.csdn.net/qq_25806863/article/details/71126867

  • 相关阅读:
    IO库 8.5
    IO库 8.4
    标准模板库——IO库
    IO库 8.3
    IO库 8.2
    IO库 8.1
    CF 599D Spongebob and Squares(数学)
    Django入门学习(一)
    hdu 5733
    uva 11210
  • 原文地址:https://www.cnblogs.com/jianpanwuzhe/p/8496918.html
Copyright © 2011-2022 走看看