并发流程控制 CountDownLatch
public void test() {
final int COUNT = 10;
final CountDownLatch countDownLatch = new CountDownLatch(COUNT);
for (int i = 0; i < COUNT; i++) {
Thread thread = new Thread("work Thread" + i) {
@Override
public void run() {
// 当你启动了一个线程,需要等到他结束
countDownLatch.countDown();
}
};
thread.start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void test2() throws InterruptedException {
final CountDownLatch startLatch = new CountDownLatch(1);
for (int i = 0; i < 10; i++) {
Thread thread = new Thread("work Thread" + i) {
@Override
public void run() {
try {
//当你启动很多线程, 你需要这些线程在等到通知后才真正可始
startLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
startLatch.countDown();
}
并发流程控制
public class performaceTest {
private int threadCount;
private CyclicBarrier barrier;
private int loopCount = 10;
public void PerformaceTest(int threadCount) {
this.threadCount = threadCount;
barrier = new CyclicBarrier(threadCount, new Runnable() {
@Override
public void run() {
collectTestResult();
}
});
for (int i = 0; i < threadCount; i++) {
Thread thread = new Thread("test-thread" + i) {
@Override
public void run() {
for (int j = 0; j < loopCount; j++) {
doTest();
try {
//使用Barrler来实现并发性能测试的聚合点
barrier.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
}
// 以下是doxx方法
private void doTest() {}
private void collectTestResult() {}
}
使用定时器
定时线程池服务
Executors 是ScheduledExecutorService 的工厂类,你可以创建你需要的线程池
1.5 以后就不建议使用java.util.Timer,因为他性能不如ScheduledExecutorService
大规模定时器TimerWheel
timerWheel这个算法最早设计用来实现BSD内核中定时器的,后来被广泛应用到
ACE 框架中 是BSD算法中的经典
并发的三大定律
Amdahl定律
Gene Amdahl 发现在计算机体系架构设计过程中,某个部件的优化对整个架构的优化和改善是有上限的
Gustafson定律
Gustafson假设随着处理器个数的增加,并行与串行的计算总数量也是可以增加的,认为加速系数几乎跟处理器个数成正比
Sun-Ni定律
充分利用存储空间等计算资源,尽量增大问题规模以产生更好/更精确的解 线程操作的方法
Start 启动一个线程实例,执行run方法
Join 一直阻塞直到其他线程退出
Interrupt 中断其他线程,线程如果在一个方法中被阻塞,会对interrupt操作做出回应,并在这个方法执行的过程中抛出interrupException,否则线程中的中断状态被设定
Stop suspend resume destory 这些不应该使用,应该使用interrupt()或者volatile标示告诉线程下一步该作什么
“未捕获异常”处理器,对没有捕获的异常进行处理
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 操作方法
}
});
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
//在此对没有捕获的异常进行处理
}
});
thread.start();
死锁
最容易导致死锁的对象monitor,阻塞wait()和notify()也容易产生死锁
饥饿
Starvation是因为一个线程长时间占用锁而导致其他线程一直处于等待状态
活锁
liveLoce 线程花费大量资源来处理协调资资源的访问,而没有真正的干活
线程协作
Wait/notify 用于一个线程通知另一个线程所需的条件状态已就绪,最常用到线程在循环中休眠,直到获取特定条件的场景
示例代码如下:
public class Latch {
private final Object lock = new Object();
private volatile boolean flag = false;
public void waitTillChange() {
synchronized (lock) {
while (!flag) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void change() {
synchronized (lock) {
flag = true;
lock.notifyAll();
}
}
}
注:wait notify notifyAll 必须在synchronized修饰的代码块中执行,否则会抛出
IllegalMonitorStateException异常
在循环条件wait的时候一定要设定循环的条件
保证在调用notify和notifyAll之前,提供符合线程退出等待的权限
高级并发对象
Lock对象
执行器rnnable对象
并发集合 BlockingQueue concurrentMap ConcurrentNavigableMap
原子变量
同步器 semaphores mutexes barriers latches
锁同步法
比较并交换(compare And sparc)
CAS包括三个操作:内存位置(V) 预期原值(A)和新值(B)
CAS 的并发算法,称为无锁算法