有书共读】java核心技术卷1--第14章

======================java核心技术卷1第14章----并发==============
主要内容:
    1 线程,中断线程,线程状态,线程属性
    2 同步与阻塞队列
    3 线程安全的集合
    4 Callable与Future
    5 执行器与同步器
    6 线程与Swing
    
==============================================================================

1 线程,中断线程,线程状态,线程属性

    1.1 线程 
        操作系统中一个程序同事可以执行多个任务。通常每个任务成为一个线程。
        在这里的程序可理解为进程,一个进程至少有一个线程
        
        使用线程执行一个任务的步骤:
            1) 将任务代码移到实现Runnable接口类的run方法中
                public interface Runnable{
                    void run();
                }
            2) 由Runnable创建一个Thread对象
                Thread t =new Thread(r);
            3) 启动线程
                t.start();
                
    1.2 中断线程
        使用interrupt方法可以请求终止线程
    
    1.3 线程状态
        New(新创建)
        Runnable(可运行)
        Blocked(被阻塞)
        Waiting(等待)
        Timed waiting(计时等待)
        Terminated(被终止)
        
        被阻塞线程和等待线程
        当线程处于被阻塞或等待状态时,它暂时不活动:
        1. 当一个线程试图获取一个内部的对象锁,而该锁被其他线程持有,则该线程进入阻塞状态

        2. 当线程等待另一个线程通知调度器一个条件时,它自己进入等待状态

        3. 有几个方法有一个超时参数,调用它们导致线程进入计时等待状态。带有超时参数的方法:
            Thread.sleep(), Object.join(), Lock.tryLock(), Condition.await()
    
    1.4 线程属性
    
        线程优先级
            在Java程序设计语言中,每一个线程有一个优先级。默认情况下,一个线程继承它的父线程的优先级。
            可以使用setPriority方法设置一个线程的优先级
        
        守护线程
            可以调用t.setDaemon(true);将线程转换为守护线程。守护线程的唯一用途是为其他线程提供服务。
            守护线程应该永远不去访问固有资源(文件,数据库),因为它会在任何时候甚至在一个操作的中间发生中断
            
        未捕获异常处理器
            线程的run方法不能抛出任何受查异常,但是,非受查异常会导致线程终止。这种情况线程就死亡了。
            但是,不需要任何catch子句来处理可以被传播的异常。相反的在线程死亡之前,异常被传递到一个用于未捕获异常的处理器。
            这个处理器必须属于一个实现了Thread.UncaughtExceptionHandler接口,这个接口只有一个方法:
            void uncaughtException(Thread t,Throwable e)
            可以用setUncaughtExceptionHandler方法为任何线程安装一个处理器,也可以使用Thread类的静态方法
            setDefaultUncaughtExceptionHandler为所有的线程安装一个默认的处理器。若没有安装默认的处理器,则默认的处理器为空
            如果不为独立的线程安装处理器,此时的处理器就是该线程的ThreadGroup对象。
        
2 同步与阻塞队列
    实际应用中,若两个或以上的线程对同一个数据进行读取,则存在竞争条件
    
    2.1 竞争条件存在例子:银行存取款的例子
    
    2.2 锁对象
        为防止多个线程并发访问出现干扰的情况,可以对访问的代码块加一个锁,一个线程拿到锁后就可以访问代码块,
        其他线程只能等待,当代码执行完毕,线程释放锁,其他线程拿到锁后才能访问代码块,保证了数据的安全性,避免出现脏数据
        
        锁的作用:
            保护代码块,任何时候只有一个线程执行被保护的代码
            锁可以管理试图进入被保护代码块的线程
            可以拥有一个或多个条件对象
            每个对象可以管理那些已经进入被保护代码块但是还不能运行的线程
            
        Java的synchronized关键字可以实现这一目的,使用实例:
            public synchronized void method(){
                method body;
            }
        
    2.3 监视器
        由于锁和条件不是面向对象的,监视器则是线程同步的一种面向对象解决方案,不需要开发人员考虑如何加锁的问题
        监视器特性:
            只包含私有域的类
            每个监视器的对象有一个相关的锁
            使用该锁对所有方法进行加锁
            该锁可以有任意多个相关条件
            
    2.4 读写锁
        readLock()  可以被多个读操作公用的读锁,会排斥所有写操作
        writeLock()  得到一个写锁,排斥其他的读操作和写操作
        
    2.5 阻塞队列
        对于多线程问题,可以通过一个或多个队列以优雅且安全的方式将其形式化,使用队列可以安全的从一个线程
        向另一个线程传递数据。
        当试图向队列添加元素而队列已满,或移除队列元素队列为空时,阻塞队列导致线程阻塞
        阻塞队列的方法有:add, element, offer, peek, poll, put, remove, take
        
3 线程安全的集合
    java.util.concurrent包提供了映射、有序集和队列的高效实现:
    ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet和ConcurrentLinkedQueue

4 Callable与Future
    Runnable封装一个异步运行的任务,可理解为一个没有参数和返回值的异步方法。
    Callable和Runnable类似,但是又返回值,Callable接口是一个参数化的类型,只有一个方法Call
    Future保留异步计算的结果,启动计算,将Future对象交给线程,然后忘记它。
    Future对象的所有者再结果计算好之后就可以获得它
    
5 执行器与同步器
    构建一个新的线程是有一定代价的,因为涉及与操作系统的交互。如果程序中创建大量的生命期很短的线程,
    就应该使用线程池。
    执行器类有许多静态工厂方法用来构建线程池
    
    同步器有:
    CyclicBarrier, Phaser, CountDownLatch, Exchanger, Semaphore, SynchronousQueue
    
6 线程与Swing
    当程序需要做某些耗时的操作时,应该启动另外一个线程,而不是阻塞用户接口
    Swing不是线程安全的。
    
    将Swing与线程一起使用的原则:
        1)如果一个动作需要花费很长时间,在一个独立工作器线程种做这件事不要在事件分配的线程中去做
        
        2)除了事件分配线程,不要在任何线程种接触Swing组件
全部评论
老哥。看的PDF还是书啊
点赞 回复 分享
发布于 2018-11-04 10:25

相关推荐

工科女的日常:真诚建议:别再用这种花哨的模板,可以看看我发的那个零经验找实习发帖子
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务