《Android开发进阶-从小工到专家》-Android中的多线程读书笔记

目前正在阅读《Android开发进阶-从小工到专家》,书很赞,对于我这种初级人员来说挺有帮助,我希望能坚持把这个读书笔记写完,有所收获,内化成自己的知识储备。
本读书笔记只是针对个人作为学习记录而言。对应的java练习源码可以在这里下载

之前写过Android的消息机制 http://blog.csdn.net/mr_immortalz/article/details/51066869,感觉之前写的就挺好的,就不再记录了。

一.多线程的实现 - Thread和Runnable

1.Thread也是一个Runnable,它实现了Runnable接口;在Thread类中有一个Runnable类型的target字段,代表要被执行在这个子线程的任务。

2.实际上最终被线程执行的任务是Runnable,而非Thead。Thread只是对Runnable的包装。

3.当启动一个线程时,如果Thread的target(即Runnable)不为空,则会在子线程中执行这个target(即Runnable)的run,否则执行该线程自身的run函数。

new Thread(){
            @Override
            public void run() {
                //耗时操作,此时target为空
            }
        }.start();
new Thread(new Runnable() {
            @Override
            public void run() {
                //耗时操作,此时target不为空
            }
        }).start();

常用函数

函数名 作用
wait 当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁,使得其他线程可以访问。用户可以用notify、notifyAll或者指定睡眠时间来唤醒当前等待池中的线程。注意:wait、notify、notifyAll必须放在synchronized block中,否则会抛出异常。
sleep 该函数是Thread的静态函数,作用是使当前线程进入睡眠状态,因为其是静态方法,所以不会改变对象机锁。即使睡着也持有对象锁
join 等待目标线程完成后再执行
yield 让出执行权限,让其他线程得以优先执行,但其他线程能否优先执行是未知的。

见demo源码

与多线程相关的方法 - Callable、Future、FutureTask

《Android开发进阶-从小工到专家》-Android中的多线程读书笔记_第1张图片

二.线程池分类

类型 作用
FixedThreadPool
CachedThreadPool
ScheduledThreadPool
SingleThreadExecutor

1.启动指定数量的线程——ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
参数名 作用
corePoolSize 线程池中所保存的核心线程数,线程池启动后默认为空
maximumPoolSize 线程池允许创建的最大线程数
keepAliveTime 当前线程池线程总数大于核心线程数时,终止多余的空闲线程的时间
unit keepAliveTime参数的时间单位,可选值有毫秒、秒、分等。
workQueue 任务队列
threadFactory 线程工厂,通常不需要设置
handler 拒绝策略,当线程池和workQueue都满了情况下,对新任务采取的处理策略

《Android开发进阶-从小工到专家》-Android中的多线程读书笔记_第2张图片

《Android开发进阶-从小工到专家》-Android中的多线程读书笔记_第3张图片

2.定时执行一些任务——ScheduledThreadPoolExecutor


见demo源码

三.同步集合

程序中的优化策略——CopyOnWriteArrayList

见demo源码


其基本思路是:从多个线程共享同一个列表,当某个线程想要修改这个列表的元素时,会把列表中的元素Copy一份,然后进行修改,修改完成之后再将新的元素设置给这个列表,这是一种延时懒惰策略。

这里有博文介绍
http://ifeve.com/java-copy-on-write/

提高并发效率——ConcurrentHashMap

HashTable是HashMap的线程安全实现,但HashTable使用synchronized来保证线程安全,所以在竞争激烈的并发环境下表现出效率低下(所有访问HashTable的线程都必须竞争同一把锁)。
而ConcurrentHashMap使用锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据分配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。有些方法需要跨段,如size、containsValue,他们可能需要锁定整个表而不仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。

这一篇博文有介绍例子:
http://blog.csdn.net/xuefeng0707/article/details/40834595
http://ifeve.com/concurrenthashmap/

有效的方法——BlockingQueue


参考这篇博文
http://ifeve.com/java-blocking-queue/

四.同步锁

同步机制关键字——synchronized


每个对象都只有一个锁。
synchronized作用于函数时,实际上锁定的就是该函数所在类的 对象。
synchronized作用于class时则是锁的这个Class类,并非某个具体对象。

public class SynchronizedDemo {
    public synchronized void synchMethod() {
        //同步方法,锁对象
    }

    public void syncThis() {
        synchronized (this) {
            //同步块,锁对象
        }
    }

    public void syncClassMethod() {
        synchronized (SynchronizedDemo.class) {
            //同步class对象,锁Class对象
        }
    }

    public synchronized static void syncStaticMethod() {
        //同步静态方法,锁Class对象
    }
}

显示锁——ReentratLock与Condition

显示锁ReentratLock和内置所synchronized相比,具有更高灵活性
1.获取和释放的灵活性
2.轮询锁和定时锁
3.公平性

常用形式

Lock lock = new ReentrantLock();
    public void doSomething(){
        lock.lock();
        try {
            //执行某些操作
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

注意:当JVM用synchronized管理锁定请求和释放时,JVM在生成线程转储时能够包括锁定信息(能标示死锁或者其他异常行为的来源0)。Lock类只是普通类,JVM不知道具体哪个线程拥有Lock对象。

见demo源码

http://blog.csdn.net/u013256816/article/details/50445241 JAVA线程间协作:Condition

信号量Semaphore
Semaphore是一个计数信号量,它的本质是一个“共享锁”。信号量维护了一个信号量许可集,线程可以通过调用acquire()来获取信号量的许可。当信号量中有可用的许可时,线程能获取该许可,否则线程必须等待,直到有可用的为止

见demo源码

hongyang大神的这篇文章用到了信号量
Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
(之前看过有点傻傻分不清,现在算是有点小理解了)
http://blog.csdn.net/lmj623565791/article/details/38476887

五.创建异步任务更简单——AysncTask的原理

这个是AsyncTask的几个状态

public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,//待定
        /**
         * Indicates that the task is running.
         */
        RUNNING,//执行
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         */
        FINISHED,//结束
    }

注意:一个任务实例只能执行一次,如果执行第二次将会抛出异常

因为每次在执行execute的时候会去判断当前mState状态,如果不是PENDING,则抛出异常,而每次执行完毕后mState=FINISHED,所以一个任务实例只能执行一次,如果执行第二次将会抛出异常

实现一个简单的AsyncTask

见demo源码

对应的java源码下载地址(仅java源码,不是一个工程)
http://download.csdn.net/detail/mr_immortalz/9516511

推荐网址 http://ifeve.com/java-copy-on-write/
阅读书籍《Android开发进阶-从小工到专家》

你可能感兴趣的:(Android基础知识)