第一章  走入并行世界

 

关于并行的两个定律: Amdahl定律 和Gustafson定律 考虑方向不同

 

Java内存模型 JMM 原子性 可见性 有序性

 

第二章 Java并行程序基础

    

    线程创建: new Thread(Runable).start()

    线程终止: stop 方法  会立即释放锁,导致数据不一致问题,已经废弃

    线程中断: interrupt() 设置中断标识,run方法中可以依靠这个做线程退出的逻辑处理Thread.interrupted()用来判断

    等待和通知:wait()和notify()必须在synchronized中,涉及到锁的操作

    挂起和继续执行:suspend 和 resume 已经废弃

    等待线程结束和谦让:

              如果一个线程A依赖另外一个线程B,那就在A中执行B.join() 即 A要等待线程B结束

              yield()是让出CPU资源,但是还是会进行资源竞争.

    volatile关键字:保证线程间的可见性和禁止执行重排(有序性)但是不能保证原子性  JMM

    守护线程: daemon 后台线程,当用户线程都结束时,守护线程也会结束,如垃圾回收线程

    

 

第三章 JDK并发包

    1.同步控制 

       1.1可重入锁 ReentrantLock

            ReentrantLock  lock  = new ReentrantLock()

            lock.lock() 加锁

            lock.unlock解锁

            对同一个线程而言,可以重复的加锁,也要解相同次数的锁才行

            中断响应: lock.lockInterruptibly() 会对thread.interrupt()抛出异常,对其进行处理即可

            限时申请锁: lock.tryLock(time,timeUnit.xxx) 在限定时间内申请获取锁,成功返回true 失败返回false

            公平锁:  ReentrantLock  lock  = new ReentrantLock(true) 默认非公平,公平锁需要维护一个线程申请锁的队列

       1.2 重入锁好搭档: Conditon 条件

             Condition condition  =  lock.newCondition()

             condition的用法类似于object.wait() 和 object.notify()

             await()方法会使当前线程等待,同时释放当前锁,当其他线程中使用signal()或者signalAll()方法是,线程活重新获取锁,继续执行.

             当前线程被中断时也能跳出等待.

             awaitUninterruptibly() 和 await()类似,但是不会中断相应

             singal()唤醒一个线程,singalAll()唤醒所有线程.

             并发容器中使用两个condition实现队列的take和put的阻塞.见ArrayBlockingQueue源码

        1.3 允许多线程同时访问: 信号量 Semaphore 

              Semaphore (int permits) 或者 Semaphore (int permits,boolean fair)  数量 和 公平

              大家看方法就能猜如来如何使用了

              acquire() 获取一个凭证

              acquireUninterruptibly() 获取凭证对中断响应

              tryAcquire() 不等待获取凭证 类似 tryLock()

              tryAcquire(timeout,unit) 指定时间内获取凭证

              release() 释放凭证

        1.4 ReadWriteLock 读写锁

              ReentrantReadWriteLock readWriteLock = new   ReentrantReadWriteLock ();

              Lock  readLock  = readWriteLock.readLock(); 读锁

              Lock  writeLock = readWriteLock.writeLock(); 写锁

              读读不互斥,写写互斥,读写互斥.

        1.5  CountDownLatch 倒计时器

               这个很常见不就写了

        1.6  循环栅栏: CyclicBarrier

               和CountDownLatch类似但比其强大.

                CyclicBarrier(int parties,Runnable barrieraction)

                循环栅栏会阻塞 xxx.await()直到满足数目才让线程一起向下执行,且在此之前会执行一次 barrieraction中run方法 

        1.7  线程阻塞工具类: LockSupport

               它可以在线程内任意位置让线程阻塞.

                LockSupport.park() 可以阻塞当前线程,类似的还有parkNanos(),parkUntil()等实现一个闲时的阻塞

                LockSupprot.unpark(Thread) 释放指定线程的阻塞

    

 2. 线程复用:线程池

     这个就不浪费笔墨了,依托底层 ThreadPoolExecutor实现了几种常用的线程池工具,大家应该都明白的.

     线程池可以根据自己的需求进行相应的自定义处理:

     ThreadPoolExecutor提供了beforeExecute() ,afterExecute(),terminated() 方法对其进行控制.

      线程数量选取: Nthreads = Nepu * Ucpu * ( 1 + W/C) 即 cpu数量 * 目标Cpu使用率 *(1 + 等待时间与计算时间比)

      分而治之:Fork/Join框架

      ForkJoinPool.submit(ForkJoinTask) 提交任务 task.fork() 执行结束后 使用 task.join收集结果

 3. JDK并发容器

     1. 并发集合

         ConcurrenHashMap

         CopyOnWriteArrayList

         ConcurrentLinkedQueue

         BlockingQueue 

         ConcurrentSkipListMap

    2. 高效读写队列:深度剖析 ConcurentLinkedQueue

        主要通过CAS(比较交换)操作和对head及tail的算法实现高效的读写

    3. 高效读取: 不变模式下的CopyOnWriteArrayList

        任何读取操作没有锁相关操作,但是写入时候.会加锁,复制原来的集合写一个新集合后替换老集合.

    4. 数据共享通道: BlockingQueue

        前面说过其take和put的通过两个condition里相互通知实现阻塞.

    5.随机数据结构:跳表(SkipList)

       维护多层链表,链表分层,通过空间换时间的方法来实现高速的查找.