并发编程之JUC

CountDownLatch

倒计时闩锁 倒计时器
CountDoownLatch latch = new CountDoownLatch ();
latch. countDown() ; //计数减一
latch.await();//等上面计数为0时主线程才继续执行

CycleBarrier

循环栅栏

public class Demo2 {
	private Random r = new Random();
	public void meeting(CyclicBarrier c) {
		try {
		Thread.sleep(r.nextInt(4000));
		System.out.println(Thread.currentThread().getName()+"到达会议室,等待开会。。。");
			c.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+" 发言~~~~");
	}
	public static void main(String[] args) {
		Demo2 d = new Demo2();
		CyclicBarrier c = new CyclicBarrier(10,new Runnable() {
			@Override
			public void run() {
				System.out.println("到齐,开始开会。。。");
			}
		});
		for(int i=0;i<10;i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					d.meeting(c);
				}
			}).start();;
		}
	
	}
}

c.await();方法继承AQS共享的,加了lock()锁线程安全的方法,一个线程等待计数减一,计数为0执行Runnable内容,最后唤醒所有线程SignalAll();重置计数,是否中断Generation对象重置;

Samphare

Future

未来任务,可以获取call方法的返回值的线程任务调度

public static void main(String[] args) throws InterruptedException, ExecutionException {
		Callable<String> call = new Callable<String>() {
			@Override
			public String call() throws Exception {
				System.out.println("正在执行任务。。。");
				return "1";
			}
		};
		FutureTask<String> f = new FutureTask<>(call);
		new Thread(f).start();
		System.out.println("干点别的。。。");
		String result = f.get();  //获取到future任务的执行结果
		System.out.println("结果为:"+result);
	}

源码:
、Callable和Runnable的区别

Runnable的run方法是异步执行的
Callable的Call方法不是异步执行的,是由Future的run方法调用的

Fork/Join

把任务分开运行 然后合并结果,充分利用CPU的资源
ForkJoinTask任务分配到ForkJoinPool池中,然后把多任务合并到一起。

并发容器

ConcurrentHashMap
put方法:1.获取键的哈希值,
		2.进入循环上下文table容器不存在就初始化容器,否则根据哈希值位运算f = tabAt(tab, i = (n - 1) & hash)出node节点f
		3.对F节点CAS无锁赋值casTabAt(tab, i, null, new Node(hash, key, value, null))赋值成功结束流程,赋值失败说明有其他线程并发的对这个引用的node节点赋值了,那么就break跳出循环,从头再来。
		4.F节点有值的话,对F节点加Sync锁,获取锁的话那么就可以任意操作F,先判断tabAt(tab, i) == f是否是原来的F节点了。可能获取锁比较慢已经有线程删除改节点了。
		5.获取锁后判断是单项链表,是就进入循环依次比较key存在否,存在替换旧值,不存在最后追加节点,
		6.不是的话链表就红黑树上增加节点。
		7.最后比较链表的长度是否大于8(binCount >= TREEIFY_THRESHOLD)是就转化为红黑树。

HashTable
线程安全的,但是直接在put()方法上加Sync,锁的粒度很大,那么就就串行的执行,单线程的效果。
HashMap
是线程不安全的

ConcurrentLinkedQueue
public boolean offer(E e) {
        checkNotNull(e);
        final Node<E> newNode = new Node<E>(e);
        for (Node<E> t = tail, p = t;;) {
            Node<E> q = p.next;
            if (q == null) {
                if (p.casNext(null, newNode)) {
                    if (p != t) // hop two nodes at a time
                        casTail(t, newNode);  // Failure is OK.
                    return true;
                }
                // Lost CAS race to another thread; re-read next
            }
            else if (p == q)
                p = (t != (t = tail)) ? t : head;
            else
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }
public E poll() {
        restartFromHead:
        for (;;) {
            for (Node<E> h = head, p = h, q;;) {
                E item = p.item;
                if (item != null && p.casItem(item, null)) {
                    if (p != h) // hop two nodes at a time
                        updateHead(h, ((q = p.next) != null) ? q : p);
                    return item;
                }
                else if ((q = p.next) == null) {
                    updateHead(h, p);
                    return null;
                }
                else if (p == q)
                    continue restartFromHead;
                else
                    p = q;
            }
        }
    }
BlockingQueue
  • ArrayBlockingQueue
  • LinkedBlockingQueue
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值