JAVA并发编程2

说明:先上代码,笔记后续补充

public class CoderTest1 {

private static Object key;

public static void main(String[] args) {

//同步容器 Vector HashTable Collections.synchronizedList()
//如果迭代过程中发生修改,并发修改异常 修改线程独立copy一份集合(这样会导致不能得到最新的数据,效率有影响)
/*多个线程操作容易抛出ArrayIndexOutOfBoundsException异常
* Vector<Object> vector = new Vector<>();
int lastSize = vector.size()-1;
vector.remove(lastSize);
* */
// Vector<Object> vector = new Vector<>();
// synchronized (key){
// int lastSize = vector.size()-1;
// vector.remove(lastSize);
// }
//这种情况会出现并发修改异常 ConcurrentModificationException
// ArrayList<Object> list = new ArrayList<>();
// list.add(1);
// list.add(1);
// list.add(1);
// list.add(1);
// list.add(1);
// for (Object obj : list){
// System.out.println(obj);
// list.remove(obj);
// }

//并发容器 ConcurrentHashMap 分段锁 每一个链表上一个锁,1.8之后好像是node锁
//map.putIfAbsent 只有key不存在才会操作成功,不会覆盖
//CopyOnWriteArrayList/Set 应用场景:读操作多,写操作很少
//阻塞队列
// 先进先出,如果队列为空则阻塞
// ConcurrentHashMap map = new ConcurrentHashMap();
// map.putIfAbsent(1,2);
// map.putIfAbsent(1,3);
// System.out.println(map);
//
// CopyOnWriteArrayList<Object> list = new CopyOnWriteArrayList<>();
// BlockingQueue queue = new ArrayBlockingQueue(2);

// 1闭锁 2栅栏 3信号量
//到达栅栏之后需要所有线程执行完之后才能继续执行其他线程
// final CountDownLatch latch = new CountDownLatch(2);
// //第一个线程
// new Thread(){
// public void run(){
// try {
// System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
// Thread.sleep(3000);
// System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
// latch.countDown();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }.start();
// //第二个线程
// new Thread(){
// public void run(){
// try {
// System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
// Thread.sleep(3000);
// System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
// latch.countDown();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }.start();
//
// try {
// System.out.println("等待两个子线程执行完毕。。。");
// //闭锁
// latch.await();
// System.out.println("两个子线程已经执行完毕。。。");
// System.out.println("继续执行主线程");
// } catch (InterruptedException e) {
// e.printStackTrace();
// }

int N = 4;
CyclicBarrier barrier = new CyclicBarrier(N);
for (int i=0; i<N; i++){
new Writer(barrier).start();
}
int workNum = 8;//工人数目
Semaphore semaphore = new Semaphore(5);//信号量,机器数目
for (int i=0; i<workNum; i++){
new Worker(i,semaphore).start();
}
}

//用于栅栏
static class Writer extends Thread{
private CyclicBarrier cyclicBarrier;
public Writer(CyclicBarrier cyclicBarrier){
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run(){
System.out.println("线程"+Thread.currentThread().getName()+"正在写入数据。。。");
try {
Thread.sleep(5000);
System.out.println("线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入数据。。。");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("所有线程写入数据完毕,继续执行其他任务。。。");
}
}

//用于信号量
static class Worker extends Thread{
private int num;
private Semaphore semaphore;
public Worker(int num, Semaphore semaphore){
this.num = num;
this.semaphore = semaphore;
}
@Override
public void run(){
try {
semaphore.acquire();
System.out.println("工人"+this.num+"占用一个机器生产。。。");
Thread.sleep(3000);
System.out.println("工人"+this.num+"释放出机器");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

同步容器存在的问题:
  如下代码所示:1.如果获取到lastSize之后有其他线程删除了vector中的元素,会发生ArrayIndexOutOfBoundsException异常需要手动加锁.
         2.如果迭代过程中发生了修改,会发生并发修改异常,即java的快速失败机制。
例1:

Vector<Object> vector = new Vector<>();
int lastSize = vector.size()-1;
vector.remove(lastSize);

例2:

ArrayList<Object> list = new ArrayList<>();
list.add(1);
list.add(1);
list.add(1);
list.add(1);
list.add(1);
for (Object obj : list){
System.out.println(obj);
list.remove(obj);
}


并发容器说明:

1.

这个方法执行put的时候会做判断,如果没有才会执行put

ConcurrentHashMap map = new ConcurrentHashMap();
map.putIfAbsent(1,2);

2.

当有写操作的时候单独copy一份集合

CopyOnWriteArrayList/Set     应用场景:读操作多,写操作很少

3.阻塞队列,类似水管,先进先出

  主要有put和take两个方法,如果队列中没有东西,执行take方法,那么就会阻塞等待执行了put方法之后才会继续执行take。

BlockingQueue

4.闭锁

  CountDownLatch

  线程1依赖线程2,当线程2执行完毕之后线程1才会继续执行,这种情况叫做闭锁,实例代码如下:

//第一个线程
new Thread(){
public void run(){
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(3000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
//第二个线程
new Thread(){
public void run(){
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(3000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();

try {
System.out.println("等待两个子线程执行完毕。。。");
//闭锁
latch.await();
System.out.println("两个子线程已经执行完毕。。。");
System.out.println("继续执行主线程");
} catch (InterruptedException e) {
e.printStackTrace();
}

5.栅栏

  要等待所有线程执行结束之后才能继续执行,类似一个team,要等待所有人搞定之后才能继续。

6.信号量

  类似于工人和机器,比如说去上网有8个人5个机器,8个人都需要刷图,前五个人先使用机器,使用完一个释放出来一个,没使用过机器的补上,直到八个人都使用完毕。

转载于:https://www.cnblogs.com/sleepy-goblin/p/8910023.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值