A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 29198102shihao 中级黑马   /  2013-7-22 22:03  /  1644 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

jdk5 java.util.concurent包下提供的并发集合!!重要!!
传统集合线程不安全,多线程访问有问题!,原因:以Map为例
隐患1:
count=4;集合当前个数
1while(hasNext()){next 的实现cursor++;并判断如下:
}
2hasNext的实现:
if(cursor==4){return true;}
3remove(){count--;}
当读线程读时,另一个线程remove插入,写,会出问题!

隐患2:集合在遍历时,另外线程修改集合时,会出现线程不安全!如ArrayList,可以用CopyOnWriteArray代替,满足多线程操作

解决方法1:Collections.synchronizedMap(new HashMap)将原来map对象返回一个线程安全的Map对象,实现是用动态代理,对map的所有方法用synchronized{}包装,但不推荐使用!还有synchronizedSet方法
最好的解决方法是用:并发集合


1阻塞队列BlockingQueue<E>接口,固定长度的队列,当多个线程去存取,一旦队列满或空线程阻塞,doc提供了很多存的方法,1存不进去报错2返回false3阻塞,我们用的第三种
1例:main(){final BlockingQueue queue=new ArrayBlockingQueue(3);长度为3
for(2){new Thread (){run(){while(true){queue.put(1);}}}.start();}两个存线程
while(true){queue.take();}组线程取
}
2用阻塞队列的特性实现线程通讯,你一下我一下。。。一个队列不行,因为存线程可能会连续存两次,达不到轮流的效果,要用两个队列,不能再用synchronized关键字了
class Business{
BlockingQueue<integer> q1=new ArrayBlockingQueue(1);长度1,作为子线程的行走指示
BlockingQueue<integer> q2=new ArrayBlockingQueue(1);长度1作为主线程的行走指示
为了第一次让子线程先走,要预先在q2里放满,因为线程是操作Business的对象,要在构造方法里完成q2的初始化:
{
q2.put(1);
}
1 sub(){
q1.put(1); 为了保证在main线程执行后,执行,放不进去说明主线程还没执行完,就阻塞等待
代码;
q2.take(); 轮到主线程执行了!通知主线程
}

2 main(){
q2.put(1); 第一次执行时,就阻塞,直到子线程执行完
代码;
q1.take();轮到子线程执行了!通知主线程
}}

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马