Android中的线程和线程池及其源码分析:

一.基本的知识点:

#线程:  什么是线程:   线程的几种状态       实现方式和区别:

##什么是线程   什么是进程  
 回答:线程就是一个程序的分割,一个程序在开始执行到结束执行的过程分割出来执行单元就是线程吧!
  进程:一个qq就是一个进程,一个360就是一个进程,

##线程的几种状态
 使用线程,那我们就需要准备线程,线程的创建的两种方式就是:

1. 一个就是实现一个类继承 Thread,实现里面的run()方法,并使用Starat来开启线程.

2. 实现一个Runable的接口,实现里面的run方法,将这个实现了Runable的方法传递到Thread中来开启线程. 

3.还有一种不常见  使用ExecutorService、Callable、Future实现有返回结果的多线程.

 区别就是:第一: 在实现线程开启线程的过程中,继承Thread的方法有一定的局限性,因为java在只支持单继承.实现Runable的方法比较灵活,实现一个接口,不会受到影响.
 第二: 不管哪种方式,开启的线程的调用的start的方法都是Threadl里面的方法来,开启的.
  线程的第一个阶段就是 创建线程(new).  创建线程后调用strart方法,就是线程的就绪状态(Runabale);(此时,这个创建的线程就是加入到了可运行线程池中,等待获取cpu的使用权)
接下来就是: 运行状态 (RUNNABLE) 此时及时就绪状态的线程获取了cpu的使用权利,执行里面的run()方法.
  线程的阻塞状态(Blocked) : 原因就是此时没有的cpu的执行权利,此时不在运行,
阻塞的三种情况:
1. 调用了 wait()方法,jvm会把该线程放到等待池中.
2. 同步阻塞,为了线程的安全,需要线程的安全,我们需要获取同步锁,同步锁此时被别的线程调用,jvm会把这个线程放置的锁池中.
3. 运行sleep方法或者是join()方法的时候
  
###总结: 
☆☆线程的状态: 

– 第一创建线程的状态 
– 第二就是线程执行start()方法后处于就绪状态 
– 第三就是 获取cpu后执行,就是运行状态
– 第四:阻塞状态  阻塞的分三种情形
– 第五:运行完毕  死亡状态
##说说线程中wait() sleep()之间区别
第一: 方法的来源不同: wait()是Obiect类中, sleep是在 Thread类中;
第二:就是执行过程中是不是是否同步锁,wait()方法在执行的过程中是会释放同步锁的,需要人们唤醒线程()使用noti或者是notifyall,但是线程执行Sleep后,是不会释放同步锁的,可以设置睡眠的时间,时间一到会自己尝试获取cpu执行权限来继续执行! 执行sleep()的线程也可以强制打断.
第三;方法的执行过程  wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而
sleep可以在任何地方使用;
第四; 关于处理异常    sleep需要处理异常,wait()不需要
##☆☆☆Final、finally、finanlize()的区别
– final是用来修饰属性  显示方法   修饰类的    作用 修饰变量表示的属性是不可变的,  修饰方法标识这个方法不能够被覆盖   修饰类,标识的类不能够被继承; 
– finally异常处理中出现的,表示的是这个部分一定会执行,一般用于关流等操作.
– finanlize() 这个方法是Object类的一个方法,在垃圾(garbage)收集器(collector)执行的时候会滴啊用被回收队形的此方法,可以覆盖此方法提供垃圾收集时其他资源的回收,例如关闭文件等.

#线程安全

线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步.

我们常见的线程安全的类.

(1)Vector是线程安全的,ArrayList是线程不安全的
(2)StringBuffer是线程安全的,StringBuilder是线程不安全的
(3)Hashtable是线程安全的,HashMap是线程不安全的

#多线程并发和怎么处理多线程并发操作(注意区别多线程的并行)

        (1)并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)
(2)并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。
(3)比如我跟两个网友聊天,左手操作一个电脑跟甲聊,同时右手用另一台电脑跟乙聊天,这就叫并行。
(4)如果用一台电脑我先给甲发个消息,然后立刻再给乙发消息,然后再跟甲聊,再跟乙聊。这就叫并发。

#线程同步的几种方法

线程同步的7种方法

二.Android中线程池

   Android中的线程池好处:

第一点: 线程池中有已经创建的线程,这样可以避免因为使用线程的创建和销毁带来的性能的开销.

第二点: 能有效限制线程池中的最大并发数(maximumPoolSize)来设置的,避免因为线程之间抢夺系统资源而出现阻塞现象.

第三点: 线程池中可以对线程进行简单的管理,比如: 线程的定时执行,指定间隔循环执行等.

   Android中的线程池来源于java中Executor(接口). 在Android中真正实现线程池的是一个  ThreadPoolExecutor实现的,在AsyncTask中也会有一个很相似的类 (Thread_ Pool_Executor ) 我们先看一下源码和他的构造方法:

  这个类的类型:

public class ThreadPoolExecutor extends AbstractExecutorService {
//其他代码
}

继续追查:

public abstract class AbstractExecutorService implements ExecutorService {
//其他代码:
}

最后,是继承的Executor这个接口:

public interface ExecutorService extends Executor {
//其他代码
}

下面是

ThreadPoolExecutor

的构造方法:

构造方法:
 /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default rejected execution handler.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

第一个参数: corePoolSize 值得就是线程池的核心线程数:

一般情况或者是默认情况下,核心线程数会在线程池中一直存活,即使是在闲置的状态下,如果设置 allowCoreThreadTimeOut(true),核心线程也就会有超时策略,也就是在等待任务的时候所用的时间超出设置的事件,核心线程也会被终止.

第二个参数: 线程池所能容纳的最大线程数(maximumPoolSize).当活动线程数达到这个数值后,后续的新任务将会被阻塞.

第三个参数:  非核心线程闲置时的超时时长,超过这个时长会被回收,allowCoreThreadTimeOut(true)此时,超时时长也会在核心线程中生效,

第四个参数:  TimeUnit   超时时长参数的单位设置:  主要单位是: 

public enum TimeUnit {
//单位的定义
}

主要的参数:

        TimeUnit.MILLISECONDS;   //  毫秒
        TimeUnit.SECONDS;        // 秒
        TimeUnit.MINUTES;        // 分钟
        TimeUnit.HOURS;         //小时
        TimeUnit.DAYS;           //天

第五个参数:   workQueue  线程池中的任务队列;通过线程池的executor()提交的Runable对象会存贮在这个参数中.

public interface BlockingQueue<E> extends Queue<E> {
//其他代码
}

上面可以看出泛型就是Runable的类型的

第六个参数: 线程工厂,为了给线程池提供创建线程的功能. 


注意: 当线程池无法在继续执行新任务时,这可能是任务队列满了或者是无法成功执行任务,此时会调用RejectedExecutionHandler 的rejectedExecutoion()来通知调用者.

public interface RejectedExecutionHandler {

    /**
     * Method that may be invoked by a {@link ThreadPoolExecutor} when
     * {@link ThreadPoolExecutor#execute execute} cannot accept a
     * task.  This may occur when no more threads or queue slots are
     * available because their bounds would be exceeded, or upon
     * shutdown of the Executor.
     *
     * <p>In the absence of other alternatives, the method may throw
     * an unchecked {@link RejectedExecutionException}, which will be
     * propagated to the caller of {@code execute}.
     *
     * @param r the runnable task requested to be executed
     * @param executor the executor attempting to execute this task
     * @throws RejectedExecutionException if there is no remedy
     */
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

线程池执行任务时候的规则:

 第一点: 在执行任务的时候,如果此时的线程数量没有达到核心线程的数量,则直接启动一个核心线程来执行任务.

第二点; 在执行任务的时候,此时执行任务的线程已经达到或者说已经超过核心线程的数量,此时任务会被存放到任务队列中进行排队,等待执行.

第三点: 如果此时的任务队列里面都满了,无法插入到任务队列中,关键此时的线程数量还没有超过最大线程数(maximumPoolSize),此时会启动一个非核心线程来执行任务.

第四点: 综合上面第三点的情况,并且此时的最大线程数量已经到到线程池设置的数量,将会拒绝任务,此时会调用RejectedExecutionHandler 的rejectedExecutoion()来通知调用者.

第三: Android中线程池的分类:(四种)

分别是: FixedThreadPool      CachedThreadPool      ScheduledThreadPool           SingleThreadExecutor


第一: FixedThreadPool   

创建; 通过使用Executors的newFixedThreadPool来创建的,

特点: 他是一种线程数量固定的线程池,没有超时策略,除非线程池关闭,不然里面的线程不会回收.只有核心线程,当所有的核心线程都处于一种执行任务的状态,新的任务会处于等待状态,直到有核心线程空闲下来.任务队列也是没有限制.


  优势: 能够更快的响应外界的请求.

public class Executors {

    /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * {@code nThreads} threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
//其他代码:

}

第二种: SingleThreadExecutor

创建: 通过Executors的newSingThreadExecutor()来创建,

特点:通过配置我们知道,核心线程数是1,意味着线程池的最大线程数量也是1,没有超时策略;

他确保了所有的任务都在同一个线程中按照顺序执行,是的所有的任务都是在用一个线程中,不需要考虑线程同步的问题.

 /**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }

第三种:CachedThreadPool     

创建: 通过Executors的newCachedThreadPool()来创建

特点:核心线程数是0,没有核心线程数,只有非核心线程数,并且是Integer.MAX_VALUE,这个数是很大的,可以认为线程池的最达线程数目是任意大的,这就导致了,有新的任务的时候到来,立即会执行任务,有闲置线程会启用,没有闲置线程会马上创建非核心线程来执行任务,当所有的线程都处于限制状态,有超时策略,超时60s都会被回收.间接导致了线程池中的任务队列是不能插入任务的,SynchronousQueue是相当于是一个无法存贮元素的队列.

  优势: 比较适合用来执行大量的但是耗时较少的任务.

 /**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }

第四种:ScheduledThreadPool          

创建: 通过Executors的newcheduledThreadPool()来创建,

特点:核心线程数是固定的,非核心线程数是不固定的(任意大),相当于是FixedThreadPool(核心线程数固定)和CachedThreadPool的(非核心线程数是任意的)结合;

  优势: 主要用于执行定时任务和具有固定周期的重复任务.

    /**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }

/**
     * Creates a new {@code ScheduledThreadPoolExecutor} with the
     * given core pool size.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); }

第四: AsyncTask的线程池源码分析:

   AsyncTask封装了线程池和Handler ,线程池主要是两个: 分别是SerialExecutor和THREAD_POOL_EXECITOR;

 Handler是指InternalHandler.线程池SerialExecutor主要用于任务的排队.真真执行任务的是THREAD_POOL_EXECITOR线程池.InternalHandler主要是用来执行环境从线程池切换到主线程中去.

再次主要看看线程池的源码,后一篇会源码分析异步任务,说明优缺点.


public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // We want at least 2 threads and at most 4 threads in the core pool, // preferring to have 1 less than the CPU count to avoid saturating // the CPU with background work  private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;  private static final int KEEP_ALIVE_SECONDS = 30; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); } }; private static final BlockingQueue<Runnable> sPoolWorkQueue =  new LinkedBlockingQueue<Runnable>(128);

可以看出: 核心线程数是: cpu核心数+1;

线程池的最大线程数: cpu核心数的2倍+1;

核心线程数没有超时策略,非核心线程数的设置超时时间30s , 有的写的是是一秒,我看源码是还需要验证.

任务队列是128;

/**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }


    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/kunkun5love/article/details/61059269
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞