JDK并发包

整理来源:http://www.javashuo.com/article/p-xkdlaiet-cc.htmlhtml

ReentrantLock

        可重入: 单线程能够重复进入,但要重复退出
        可中断: lock.lockInterruptibly()
        可限时: 超时不能得到锁,就返回false,不会永久等待构成死锁
        公平锁: 先来先得, public ReentrantLock(boolean fair), 默认锁不公平的, 根据线程优先级竞争
        reentrantlock须要手工释放锁经过调用(unlock()方法),默认为非公平锁,new ReentrantLock(true)设置为公平锁能够防止饥饿现象
      数组

public interface Lock {

     // 获取锁,若当前lock被其余线程获取;则此线程阻塞等待lock被释放
     // 若是采用Lock,必须主动去释放锁,而且在发生异常时,不会自动释放锁
    void lock();

    // 获取锁,若当前锁不可用(被其余线程获取);
    // 则阻塞线程,等待获取锁,则这个线程可以响应中断,即中断线程的等待状态
    void lockInterruptibly() throws InterruptedException;

    // 来尝试获取锁,若是获取成功,则返回true;
    // 若是获取失败(即锁已被其余线程获取),则返回false
    // 也就是说,这个方法不管如何都会当即返回
    boolean tryLock();

    // 在拿不到锁时会等待必定的时间
    // 等待过程当中,能够被中断
    // 超过期间,依然获取不到,则返回false;不然返回true
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    // 释放锁
    void unlock();

    // 返回一个绑定该lock的Condtion对象
    // 在Condition#await()以前,锁会被该线程持有
    // Condition#await() 会自动释放锁,在wait返回以后,会自动获取锁
    Condition newCondition();
}

condition:      多线程

public interface Condition {
    void await() throws InterruptedException;
    void awaitUninterruptibly();
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    boolean awaitUntil(Date deadline) throws InterruptedException;
    void signal();
    void signalAll();
}

说明
await()方法会使当前线程等待,同时释放当前锁,当其余线程中使用signal()时或者signalAll()方法时,线程会从新得到锁并继续执行。或者当线程被中断时,也能跳出等待。这和Object.wait()方法很类似。
awaitUninterruptibly()方法与await()方法基本相同,但awaitUninterruptibly()方法不会在等待过程当中响应中断。
singal()方法用于唤醒一个在等待中的线程。相对的singalAll()方法会唤醒全部在等待中的线程。这和Obejct.notify()方法相似。
condition.await()方法必须在lock.lock()与lock.unlock()方法之间调用并发

Semaphore信号量
    做用:
控制线程的并发数量
    Semaphore主要方法:
          acquire( int permits ) 参数做用,及动态添加 permits 许可数量
          availablePermits() 返回 Semaphore 对象中的当前可用许可数
         drainPermits() 方法可获取并返回当即可用的全部许可(通路)个数,并将可用许可置为0。
         getQueueLength() 获取等待许可的线程个数。
    hasQueuedThreads() 判断有没有线程在等待这个许可。
         Semaphore semaphore = new Semaphore(int permits , boolean isFair) isFair 为 true,则表示公平,先启动的线程先获锁
         tryAcquire() 、 tryAcquire(int permits)、 tryAcquire(int permits , long timeout , TimeUint unit)获取许可通道数timeout时间内
ReadWriteLock:
读写分离锁, 能够大幅提高系统并行度.
    读-读不互斥:读读之间不阻塞。
    读-写互斥:读阻塞写,写也会阻塞读。
    写-写互斥:写写阻塞。
CountDownLatch:倒数计时器

CountDownLatch(int count) //实例化一个倒计数器,count指定计数个数
countDown() // 计数减一
await() //等待,当计数减到0时,全部线程并行执行

public class CountDownLatchDemo implements Runnable{

    static final CountDownLatch latch = new CountDownLatch(10);
    static final CountDownLatchDemo demo = new CountDownLatchDemo();

    @Override
    public void run() {
        // 模拟检查任务
        try {
            Thread.sleep(new Random().nextInt(10) * 1000);
            System.out.println("check complete");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //计数减一
            //放在finally避免任务执行过程出现异常,致使countDown()不能被执行
            latch.countDown();
        }
    }


    public static void main(String[] args) throws InterruptedException {
        ExecutorService exec = Executors.newFixedThreadPool(10);
        for (int i=0; i<10; i++){
            exec.submit(demo);
        }

        // 等待检查
        latch.await();

        // 发射火箭
        System.out.println("Fire!");
        // 关闭线程池
        exec.shutdown();
    }
}

CyclicBarrier:循环栅栏
1.CyclicBarrier(int parties, Runnable barrierAction) 建立一个CyclicBarrier实例,parties指定参与相互等待的线程数,barrierAction指定当全部线程到达屏障点以后,首先执行的操做,该操做由最后一个进入屏障点的线程执行。
2.CyclicBarrier(int parties) 建立一个CyclicBarrier实例,parties指定参与相互等待的线程数。
3.getParties() 返回参与相互等待的线程数。
4.await() 该方法被调用时表示当前线程已经到达屏障点,当前线程阻塞进入休眠状态,直到全部线程都到达屏障点,当前线程才会被唤醒。
5.await(long timeout, TimeUnit unit) 该方法被调用时表示当前线程已经到达屏障点,当前线程阻塞进入休眠状态,在timeout指定的超时时间内,等待其余参与线程到达屏障点;若是超出指定的等待时间,则抛出TimeoutException异常,若是该时间小于等于零,则此方法根本不会等待。
6.isBroken() 判断此屏障是否处于中断状态。若是由于构造或最后一次重置而致使中断或超时,从而使一个或多个参与者摆脱此屏障点,或者由于异常而致使某个屏障操做失败,则返回true;不然返回false。
7.reset() 将屏障重置为其初始状态。
8.getNumberWaiting() 返回当前在屏障处等待的参与者数目,此方法主要用于调试和断言。

static class TaskThread extends Thread {
        
        CyclicBarrier barrier;
        
        public TaskThread(CyclicBarrier barrier) {
            this.barrier = barrier;
        }
        
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(getName() + " 到达栅栏 A");
                barrier.await();
                System.out.println(getName() + " 冲破栅栏 A");
                
                Thread.sleep(2000);
                System.out.println(getName() + " 到达栅栏 B");
                barrier.await();
                System.out.println(getName() + " 冲破栅栏 B");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        int threadNum =5;
        CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 完成最后任务");
            }
        });
        
        for(int i = 0; i < threadNum; i++) {
            new TaskThread(barrier).start();
        }
    }
}

LockSupport:一个线程阻塞工具, 能够在任意位置让线程阻塞.
 dom

LockSupport.park();
LockSupport.unpark(t1);

优势:LockSupport不须要在同步代码块里 。因此线程间也不须要维护一个共享的同步对象了,实现了线程间的解耦
          unpark函数能够先于park调用,因此不须要担忧线程间的执行的前后顺序ide

并发容器函数

synchronizedMap
ConcurrentHashMap
BlockingQueue:阻塞队列, 主要用于多线程之间共享数据.当一个线程读取数据时, 若是队列是空的, 则当前线程会进入等待状态.若是队列满了, 当一个线程尝试写入数据时, 一样会进入等待状态.
CopyOnWriteArrayList:经过在新增元素时, 复制一份新的数组出来, 并在其中写入数据, 以后将原数组引用指向到新数组.其Add操做是在内部经过ReentrantLock进行锁保护, 防止多线程场景复制多份数组.而Read操做内部无锁, 直接返回数组引用, 并发下效率高, 所以适用于读多写少的场景工具

相关文章
相关标签/搜索