整理来源:http://www.javashuo.com/article/p-xkdlaiet-cc.htmlhtml
可重入: 单线程能够重复进入,但要重复退出
可中断: 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()方法之间调用并发
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(); } }
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操做内部无锁, 直接返回数组引用, 并发下效率高, 所以适用于读多写少的场景工具