程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(2)

JUC初识

发布于2021-06-12 14:42     阅读(94)     评论(0)     点赞(25)     收藏(2)


JUC

1.ReentrantLock

    a)lock写在try之前
    b)一定要记得在finally里面进行unlock()

2.信号量

acquire():void ------>尝试获取锁,如果可以正常获取到,则执行后面的业务逻辑,如果获取失败,则阻塞等待
release():void------>释放锁

//信号量演示
public class ThreadMain98 {
    public static void main(String[] args) {
        //创建信号量
        Semaphore semaphore=new Semaphore(2,true);
        ThreadPoolExecutor executor=new ThreadPoolExecutor(10,10,
                0, TimeUnit.SECONDS,new LinkedBlockingQueue<>(100));

        for (int i = 0; i <4 ; i++) {
            //创建任务
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"到达停车场");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //试图进入停车场
                    try {
                        //尝试获取锁
                        semaphore.acquire();
                        //当代码只想到此处,说明已经获取到锁
                        System.out.println(Thread.currentThread().getName()+"进入停车场---------");
                        //车辆停留的时间
                        int num=1+new Random().nextInt(5);
                        try {
                            Thread.sleep(num*1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"离开停车场...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        //释放锁
                        semaphore.release();
                    }


                }
            });
        }

    }
}

3.计数器:CountDownLauth

计数器是用来保证一组线程同时完成某个操作之后,才能继续之后的任务。
await():void-----等待(当线程数量不满足CountDownLauth的数量的时候,会执行此代码会阻塞等待,直到数量满足之后,在执行await之后的代码。)
countDown():void

CountDownLauth是如何实现的?

答:CountDownLauth里面有一个计数器,计数器的数量在初始化的时候设置,每次调用countDown()方法的时候,计数器的数量-1,直到减到0之后,就可以执行await之后的代码。

import java.util.concurrent.CountDownLatch;

/**
 * 计数器
 */
public class ThreadMain99 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch=new CountDownLatch(5);
        for (int i = 1; i <6 ; i++) {
            int finaI=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"开始起跑");
                    try {
                        Thread.sleep(finaI*1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到达终点");
                    //将计数器-1
                    latch.countDown();
                }
            }).start();
        }
        //阻塞等待
        latch.await();
        System.out.println("所有人都到达终点了,公布排名");
    }
}

在这里插入图片描述
声明计数器初始值为5
在这里插入图片描述
当计数器减到0之后,在执行await
在这里插入图片描述

CountDownLauth缺点

CountDownLauth计数器的使用是一次性的,当用完一次之后就不能使用了

4.循环屏障(循环栅栏):CyclicBarrier

await():int ------等待(CyclicBarrier里面有一个计数器,每次执行await方法的时候,计数器的数量-1,直到减到0之后,就可以执行await之后的代码,并且此时会将count值(计数器的值)重置继续利用。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
 * 循环屏障
 */
public class ThreadMain100 {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("执行了CyclicBarrier里面的Runnable");
            }
        });
        for (int i = 1; i < 11; i++) {
            int finalI=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"开始起跑");
                    try {
                        Thread.sleep(finalI*200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        System.out.println(Thread.currentThread().getName()+"等待其他人-----------");
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    //代码执行到此行,说明已经有一组代码已经满足情况
                    System.out.println(Thread.currentThread().getName()+"执行结束");
                }
            }).start();

        }
    }
}

循环屏障的使用:

在这里插入图片描述
在这里插入图片描述
1.计数器-1
2.判断计数器是否为0,如果为0执行之后的代码,如果不为0阻塞等待
当计数器为0时,首先会执行await之后的代码,将计数器重置

CyclicBarrier和CountDownLatch区别?

答:CountDownLatch计数器只能使用一次,CyclicBarrier他的计数器可以重复使用。

HashMap

HashMap底层实现结构,负载因子,哈希冲突的解决等…线程问题
HashMap------非线程安全的容器
——JDK1.7死循环(要会画出来)
——JDK1.8数据覆盖

HashMap—>数组+链表 / 红黑树
HashMap 负载因子(加载因子)0.75 扩容:16*0.75=进行扩容
0.75:尽量的避免哈希冲突所带来的性能开销问题(空间换时间的方案)

HashMap线程安全方案

ConcurrentHashMap

JDK1.7是将ConcurrentHashMap分成几个segment进行加锁(分段锁)。
JDK1.8锁优化:读的时候不加锁,写的时候加锁,使用了大量的CAS,Voiltail…

Hashtable:线程安全的容器

在这里插入图片描述
给put方法直接加锁,因此一般情况不会使用Hashtable

HashMap,ConcurrentHashMap,Hashtable区别?

  1. HashMap是非线程安全的容器,他在JDK1.7造成死循环,JDK1.8会造成数据覆盖,Hashtable和ConcurrentHashMap都是线程安全的。
  2. Hashtable实现线程安全的手段比较简单,他是在给put方法整体加了一把锁,因此性能不高,所以使用频率比较低;而ConcurrentHashMap是Hash MAp在多线程下的替代方案,他在JDK1.7的时候使用的Lock加分段锁的方案来实现线程安全的保障,而在JDK1.8的时候使用了大量的使用了大量的CAS,Voiltail来实现线程的,并且在JDK1.8读取的时候不加锁(读取的数据可能不是最新,因为读取和写入同时进行),只有在写的时候才加锁。

原文链接:https://blog.csdn.net/qq_54850622/article/details/117715269



所属网站分类: 技术文章 > 博客

作者:哦哦好吧

链接:http://www.javaheidong.com/blog/article/222384/4a47a6dfd6c1613bf2e0/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

25 0
收藏该文
已收藏

评论内容:(最多支持255个字符)