1.ConcurrenHasMap------并发包中的分段锁,分为16段。将一个整体拆分成多个小的HasTable.
比如:分成三把锁:HasTable 0-4 HasTable 4-8 HasTable 8-12,三个线程共享,通过volatile关键字设置线程可见,一个线程共享内存变量修改后其他线程立马刷新该变量.
ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个
小的HashTable,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并
发进行。把一个整体分成了16个段(Segment.也就是最高支持16个线程的并发修改操作。
这也是在重线程场景时减小锁的粒度从而降低锁竞争的一种方案。并且代码中大多共享变
量使用volatile关键字声明,目的是第一时间获取修改的内容,性能非常好。
2.CountDownLatch类--计数器
很简单,
CountDownLatch countDownLatch = new CountDownLatch(2);
countDownLatch.await();// 调用当前方法主线程阻塞 countDown结果为0, 阻塞变为运行状态
在其他线程中 countDownLatch.countDown();
// 初始化值是2,每次减1,直到=0为止 调用上面的await
3.CyclicBarrier
CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。
举个例子
public class TestABC { public static void main(String[] args){ CyclicBarrier cyclicBarrier=new CyclicBarrier(5); for(int i=0;i<5;i++){ new Writer(cyclicBarrier).start(); } } }
class Writer extends Thread{ CyclicBarrier cyclicBarrier; public Writer(CyclicBarrier cyclicBarrier){ this.cyclicBarrier=cyclicBarrier; } @Override public void run(){ System.out.println(Thread.currentThread().getName()+"开始写入数据..."); try { System.out.println(Thread.currentThread().getName()+"写入数据成功..."); cyclicBarrier.await(); System.out.println(Thread.currentThread().getName()+"所有数据执行完毕..."); } catch (Exception e) { e.printStackTrace(); } }
System.out.println(Thread.currentThread().getName()+"所有数据执行完毕...");等在五个线程都运行完写入数据成功后再运行
后再运行await后的方法。
4.Semaphore
availablePermits函数用来获取当前可用的资源数量
wc.acquire(); //申请资源
wc.release();// 释放资源
抢茅坑案例
// 剩下的资源(剩下的茅坑)
int availablePermits = wc.availablePermits();
if (availablePermits > 0) {
System.out.println(name+"天助我也,终于有茅坑了...");
} else {
System.out.println(name+"怎么没有茅坑了...");
}
//申请茅坑 如果资源达到3次,就等待
wc.acquire();
起始在这一段很不理解,主要卡在availablePermits和acquire方法上面,现在的理解是availablePermits方法获取资源,获取到了后wc.acquire();获取到,走下面的代码,没有抢到wc.acquire()就一直等待。别忘了在finally中release.