您的位置:首页 > 编程语言 > Java开发

java 并发编程实战 第二天

2015-02-15 23:08 411 查看
第四章
对象的组合

这章书看得我有点云里雾里的感觉.可能是没有好好的去实战或者什么的,更多的都是停留在看.

这本书说到现在有两点是要值得注意的.1.不变条件.2,后验条件.如果违背了这两个.就可能出现线程不安全的问题.

要保证线程安全

可以通过加锁,加内置锁

监听器模式,将对象还有内置锁保护起来.主要的优点是简单性.

线程安全委托,通过多个线程安全类来组合获得较好的线程安全(AtomicLong/加内置锁)

第五章.基础构建模块

同步容器类

还是那个问题.如果看到"先判断在修改"就可能出现不安全的问题.

//类似这种的可能会出现大问题.可能两个线程都拿到了size()为1但是有一个继续操作了.剩下那个就报错了.
publicstaticvoiddeleteLast(Vectorlist){
intlastIndex=list.size()-1;
list.remove(lastIndex);
}
//最简单最粗暴的改进方法就是直接加锁.
publicstaticvoiddeleteLast(Vectorlist){
//但是这样做会引来性能上的大问题.这个方法就直接被阻塞掉了.
synchronized(list){
intlastIndex=list.size()-1;
list.remove(lastIndex);
}
}


在容器迭代的时候不希望加锁.

ConcurrentModificationException的出现:

当他们发现在迭代过程容器中被修改的时候就会报这个错.

//这是AbstractList上面的方法.
//modCount是修改上面数字的次数
//expectedModCount是期望值,如果期望值不跟实际相等就会报错.
privatevoidcheckForComodification(){
if(l.modCount!=expectedModCount)
thrownewConcurrentModificationException();
}


解决办法:因此使用Iterator遍历集合时,不要改动被迭代的对象,可以使用Iterator本身的方法remove()来删除对象,Iterator.remove()方法会在删除当前迭代对象的同时维护modCount和expectedModCount值的一致性。

同步工具类:

闭锁(Latch):相当于一个内置锁,会直接阻塞着,await();等待,countDown(),减少一,当减为零的时候就是代表空闲.

publiclongtimeTasks(intnThreads,finalRunnabletask)
throwsInterruptedException{
//
它使用两个闭锁,分别是“起始门(startGate)”和“结束门(endGate)
finalCountDownLatchstartGate=newCountDownLatch(1);
finalCountDownLatchendGate=newCountDownLatch(nThreads);
for(inti=0;i<nThreads;i++)
{
Threadt=newThread()
{
publicvoidrun()
{
try
{
startGate.await();
task.run();
}
catch(InterruptedExceptione){//ignored
}
finally{
endGate.countDown();
}
}
};
t.start();
}
longstart=System.nanoTime();
startGate.countDown();
endGate.await();
longend=System.nanoTime();
returnend-start;
}


FutureTask:这个有点像回调函数的感觉,跟Callable搭配着一起用的.

publicstaticvoidfuture()
{
ExecutorServiceexecutor=Executors.newFixedThreadPool(10);
FutureTask<String>futureTask=newFutureTask<String>(newCallable<String>()
{
publicStringcall()
{
//真正的任务在这里执行,这里的返回值类型为String,可以为任意类型
return"simple";
}
});
executor.execute(futureTask);
try{
//取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果
Stringresult=futureTask.get(5000,TimeUnit.MILLISECONDS);
//业务处理……
System.out.println(result);
}
catch(InterruptedExceptione){
Thread.currentThread().interrupt();
}
catch(ExecutionExceptione){
//skip
}
catch(TimeoutExceptione){
//skip
}
finally{
executor.shutdown();
}
}


信号量(Semaphore):可以用作互斥体,类似(AtomicXXX);

栅栏(barrier):主要的作用就是等待所有的来亲了才动手.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: