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