Android 多线程:线程池理解和使用总结

2017-10-19  本文已影响0人  Marker_Sky
Android线程池目录.png

一、Android线程池介绍

1.1 原理

Android中的线程池概念来源于Java中的Executor,Executor是一个接口,真正的线程的实现为ThreadPoolExecutor。(ThreadPoolExecutor继承了AbstractExecutorService,AbstractExecutorService是ExecutorService的实现类,ExecutorService继承了Executor接口)。

1.2 分类

从线程池的功能特性上来说,Android中线程池主要分为4类:

1.3 优点

  1. 重用线程池中的线程,避免频繁创建和销毁线程所带来的内存开销。
  2. 有效控制线程的最大并发数,避免因线程之间抢占资源而导致的阻塞现象。
  3. 能够对线程进行简单的管理,提供定时执行以及指定时间间隔循环执行等功能。

二、 Android线程池分类

由于Android中的线程池都是直接或间接通过配置ThreadPoolExecutor来实现的,因此在介绍它们之前要先介绍ThreadPoolExecutor。

2.1 ThreadPoolExecutor介绍

ThreadPoolExecutor有多个构造方法以及参数,下面介绍比较常用的构造方法。

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    private volatile long keepAliveTime;
    private volatile boolean allowCoreThreadTimeOut;

2.2 线程池的分类

先介绍一个类Executors,这个类定义了各种参数用于创建多种线程池,最终实现还是通过ThreadPoolExecutor类。
1. FixedThreadPool (Fixed:固定的,不变的)
通过Executors的newFixedThreadPool创建,通过创建时的参数可以看出又以下几个特点:

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

2. CachedThreadPool (Cached:缓存)
通过Executors的newCachedThreadPool创建,特点:

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

3. ScheduledThreadPool(Scheduled:预定的、排定的)
通过Executors的newScheduledThreadPool创建,特点:

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    //默认闲置超时回收时常
    private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }

4. SingleThreadExecutor (单线程线程池)
通过Executors的newSingleThreadExecutor创建,特点:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

三、 Android线程池简单使用

3.1 线程池简单使用

(1)上面所说的四种常用线程池的实例化:

    //创建一个Runnable对象
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
                // do something
        }
    };
    //四种线程池执行Runnable对象
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
    fixedThreadPool.execute(runnable);
    
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    cachedThreadPool.execute(runnable);

    // 注意这里创建的是ScheduledExecutorService对象,ScheduledExecutorService是ExecutorService的子类
    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
    // 1000ms后执行runnable
    scheduledThreadPool.schedule(runnable,1000,TimeUnit.MILLISECONDS);
    // 1000ms后,每3000ms执行一次runnable
    scheduledThreadPool.scheduleAtFixedRate(runnable,1000,2000,TimeUnit.MILLISECONDS);
    isRunning = true;
    
    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    singleThreadExecutor.execute(runnable);

(2)简单使用小demo:
添加线程池开始执行和ScheduledThreadPool停止执行的两个按钮点击事件,布局就不贴了。

findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            count = 0;
            mStatueText.setText("线程开始执行,次数:"+ count);
            startThreadPool();
        }
    });
findViewById(R.id.btn_stop).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(null != scheduledThreadPool && isRunning){
                scheduledThreadPool.shutdown();
                mStatueText.setText("scheduledThreadPool线程停止,当前次数:"+ count);
                isRunning = false;
            }
        }
    });

startThreadPool();方法里Runnable每执行一次增加一次count并打到TextView上:

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
                count++;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mStatueText.setText("线程执行完毕,次数:"+ count);
                    }
                });
        }
    };

接着让所有的线程池执行这个Runnable对象,最后的结果是变量count的值从0直接到了3,然后又到5最后无限增长。
原因是除ScheduledThreadPool对象外的三个线程池很快执行了任务,ScheduledThreadPool对象的执行了两次任务,两个都延时1000ms。最后循环执行的任务一直在增加count的值。

相关文章:
Android多线程:理解和简单使用总结

上一篇 下一篇

猜你喜欢

热点阅读