Java线程池

1.概述

在Android开发中,不能在主线程进行耗时操作,运行耗时操作必须创建子线程来运行。在一些频繁的耗时操作做(如ListView中图片下载),如果每次进行耗时操作都创建一个子线程。这样的话如果进行管理所创建的子线程,它们之间相互竞争,很可能由于占用过多资源导致OOM或者死机。而且每次创建线程、销毁线程都会有资源的消耗,而线程池可以很好解决这类的问题。

线程池的优点:

1.减少资源的开销:减少了每次创建线程、销毁线程的开销。

2.提高响应速度,每次请求到来时,由于线程的创建已经完成,可以直接执行任务,因此提高了响应速度。

3.线程便于管理:线程池可以对线程的创建与停止,线程数量等等因素加以控制,使得线程在一种可控的范围内运行。

4.线程池提供了定时,定期以及可控线程数等功能的线程池。

2.ThreadPoolExecutor

构造方法:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

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

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
    ...
    ...
}


主要参数含义:

1. corePoolSize

线程池中的核心线程数,默认情况下,核心线程是已知存活在线程池中,即使他们在线程池中处于闲置状态。

2. maximumPoolSize 

线程池中所容纳的最大线程数,如果活动的线程达到这个数值以后,后续的新任务将会被阻塞。包含:核心线程数+非核心线程数。

3. keepAliveTime 

非核心线程闲置时的超时时长,对于非核心线程,闲置时间超过这个时间,非核心线程就会被回收。只有对ThreadPoolExecutor的allowCoreThreadTimeOut属性设为true的时候,这个超时时间才会对核心线程产生效果。

4. unit

用于指定keepAliveTime参数的时间单位.可以使用的单位有天(TimeUnit.DAYS),小时(TimeUnit.HOURS),分钟(TimeUnit.MINUTES),毫秒(TimeUnit.MILLISECONDS),微秒(TimeUnit.MICROSECONDS, 千分之一毫秒)和毫微秒(TimeUnit.NANOSECONDS, 千分之一微秒);

5. workQueue

线程中保存等待执行的任务的阻塞队列。当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。有下面几种队列可以选择:

ArrayBlockingQueue

限定队列的长度,如果如果没有达到核心线程数,则新建线程(核心线程)处理任务;如果当前线程数达到了核心线程数,则入队列等待。如果队列已经满了,则新建线程(非核心线程)执行任务。如果总线程数达到了最大线程数,并且队列也满了,则发生错误。

SynchronousQueue

接收到任务的时候,会直接交给线程处理,而不保留它。如果所有的线程都在工作,就新建线程来处理任务。使用这个队列的时候,都把最大线程数指定为Integer.MAX_VALUE。

LinkedBlockingQueue

接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程等于核心线程数,则进入队列等待。由于这个队列没有最大值,则所有操作核心线程数的任务都被添加到队列中,所以最大线程数的设定失效。

3.实例

public class MainActivity extends AppCompatActivity {
    private volatile int mNum =0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ThreadPoolExecutor mPool=new ThreadPoolExecutor(5,20,30, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
        for (int i = 0; i <100 ; i++) {
            Runnable runnable= new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(100);
                        mNum++;
                        Log.e("zzw","mNum="+mNum);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            mPool.execute(runnable);
        }
    }
}

结果:

 

4.四种线程池类

Java中四种具有不同功能常见的线程池。他们都是直接或者间接配置ThreadPoolExecutor来实现他们各自的功能。这四种线程池分别是newFixedThreadPool,newCachedThreadPool,newScheduledThreadPool和newSingleThreadExecutor。

4.1 newFixedThreadPool:

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

这是一种线程数量固定的线程池,核心线程数等于最大线程数。如果线程处于空闲状态,它们并不会被回收。除非这个线程池被关闭。

4.2 newCachedThreadPool:

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

线程数量不固定的线程池,它只有非核心线程,并且最大线程数为Int的最大值。当线程池中的线程都处于活动状态的时候,线程池就会创建一个新的线程来处理任务。该线程池中的线程超时时长为60秒,所以当线程处于闲置状态超过60秒就会被回收。如果所有的线程都处于闲置状态超过60秒,则 newCachedThreadPool 中是不存在任何线程的,这时它几乎不占用任何的系统资源。

4.3 newScheduledThreadPool:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

它的核心线程数是固定的,总的线程数是Int的最大值,非核心线程的超时时长为0,也就是当非核心线程处于闲置状态的时候就会被立即收回。

4.4 newSingleThreadExecutor:

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

在这个线程池中只有一个核心线程,任务队列大小没有闲置,也就是一个任务处于活动状态的时候,其他任务都会在任务队列中等候依次执行。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值