JAVA并发真讨厌(二)

举报
赵KK日常技术记录 发表于 2023/06/24 13:50:58 2023/06/24
【摘要】 JUC包下,继续根据资料整理那些不曾注意的问题,有些人云亦云的问题,能在大佬的视频中找到答案,着重看下那些颠覆常识的问题,另外,小马哥对源码的熟悉程度实在令人敬佩。         高并发要关注的问题        1.线程安全        2.减少线程同步竞争        3.合理利用状态位        4.线程池        5.超时意识        **1.什么是线程安全问题...
JUC包下,继续根据资料整理那些不曾注意的问题,有些人云亦云的问题,能在大佬的视频中找到答案,着重看下那些颠覆常识的问题,另外,小马哥对源码的熟悉程度实在令人敬佩。

         高并发要关注的问题

        1.线程安全

        2.减少线程同步竞争

        3.合理利用状态位

        4.线程池

        5.超时意识

        **1.什么是线程安全问题?**

答:多线程并发执行时,对共享内存中共享对象的属性发生修改时所导致的数据冲突问题,称之为线程安全问题

        2.线程池:所有的池化操作,我都理解为将要执行的资源放入,减少其创建与销毁的时间,且能动态的去定制获取策略,空闲策略等。

       从CountDownLatch,CyclicBarrier,Semaphore入手

     以前已经总结过关于这三个线程操作的文章[CountDownLatch 与 CyclicBarrier 和Semaphore的区别?](https://mp.weixin.qq.com/s?__biz=Mzg2ODA3NjA1MA==&mid=2247484325&idx=1&sn=7998b47b95bc706c27acebf6dab6e342&chksm=ceb09cd8f9c715cef11aa17a0d04191ec5f8cad3fec3a2f3b8f862b8ad2b18e9ca6861e6919e&token=1435792401&lang=zh_CN&scene=21#wechat_redirect)现在看下内部操作

      CyclicBarrier:

![请在此添加图片描述](https://ask.qcloudimg.com/http-save/4069641/j6rphc8tsd.png?qc_blockWidth=332&qc_blockHeight=404)

 reset:

   重置,刷新操作,reset不要轻易去用

   breakBarrier  :

```javascript
 private void breakBarrier() {        generation.broken = true;        count = parties;        trip.signalAll();    }
```

   nextGeneration:

```javascript
Updates state on barrier trip and wakes up everyone//更新线程状态并唤醒
```

项目中用于countdownLatch更多,慎用CyclicBarrire

     **3.线程池  THREADPOOL**  


 1.线程复用

        2.控制最大并发数

        3.管理线程


         **-ExecutorService的实现**

 1.ThreadPoolExecutor


         2.ScheduleThreadPoolExecutor

         3.ForkJoinPool


         **-常见的创建线程池的方式5种**

 但常用3种,在阿里巴巴开发手册中指定 

```javascript
 【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。说明:Executors 返回的线程池对象的弊端如下:1FixedThreadPool  SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM2CachedThreadPool  ScheduledThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM
```

      实际谁也不会用到Integer.MAX\_VALUE(),但是CacheThreadPool就不一定了,他不会指定线程数量,所以一旦获取线程是循环会有可能到到这个数量

![请在此添加图片描述](https://ask.qcloudimg.com/http-save/4069641/ges8mwlgfd.png?qc_blockWidth=594&qc_blockHeight=251)

 **--线程7参**

```javascript
public static ExecutorService newSingleThreadExecutor() {        return new FinalizableDelegatedExecutorService            (new ThreadPoolExecutor(1,                                     1,                                    0L,                                    TimeUnit.MILLISECONDS,                                    new LinkedBlockingQueue<Runnable>()));    }
```

在常用3种线程池中只有5参,看下全参

![请在此添加图片描述](https://ask.qcloudimg.com/http-save/4069641/cy5tav75kr.png?qc_blockWidth=761&qc_blockHeight=293)

```javascript
new ThreadPoolExecutor(1,                2,                0,                TimeUnit.SECONDS,                new LinkedBlockingDeque<Runnable>(3),                new ThreadPoolExecutor.AbortPolicy()                );
```

看下idea默认提示


![请在此添加图片描述](https://ask.qcloudimg.com/http-save/4069641/wvj6gh0gl5.png?qc_blockWidth=801&qc_blockHeight=214)

线程7参已经总结过了[线程7参](https://mp.weixin.qq.com/s?__biz=Mzg2ODA3NjA1MA==&mid=2247483985&idx=1&sn=1566a15353ae1f31b23420483f060a8c&chksm=ceb09d2cf9c7143ab6cb1e57697a3fa7d07d59cec7ce166e4a6e3f70550efbcc4fbb89ef6b5b&token=1435792401&lang=zh_CN&scene=21#wechat_redirect) 

   **4:如何获取正在运行的线程?**   

![请在此添加图片描述](https://ask.qcloudimg.com/http-save/4069641/qilnryra6n.png?qc_blockWidth=414&qc_blockHeight=415)

ThreadPoolExecutor是有before,after方法的,但是针对

newCachedThreadPool如何获取呢? 

```javascript
 public static void main(String[] args) throws InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        Set<Thread> threads = new HashSet<>();        //计数        setFactory(executorService, threads);        for (int i = 0; i < 9; i++) {            executorService.submit(() -> {            });        }        executorService.awaitTermination(10, TimeUnit.MILLISECONDS);        // System.out.println("线程池等待 \n"+threads);        threads.stream()                .filter(Thread::isAlive)                .forEach(System.out::println);        executorService.shutdown();    }
    private static void setFactory(ExecutorService executorService, Set<Thread> threads) {        if (executorService instanceof ThreadPoolExecutor) {            ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;            ThreadFactory threadFactory = threadPoolExecutor.getThreadFactory();            threadPoolExecutor.setThreadFactory(new DelegatingFactory(threadFactory, threads));        }    }
    private static class DelegatingFactory implements ThreadFactory {
        private final ThreadFactory delegate;        private Set<Thread> threads;
        private DelegatingFactory(ThreadFactory delegate, Set<Thread> threads) {            this.delegate = delegate;            this.threads = threads;        }
        @Override        public Thread newThread(Runnable r) {            Thread thread = delegate.newThread(r);            threads.add(thread);            return thread;        }    }
```

运行结果:

```javascript
Connected to the target VM, address: '127.0.0.1:50402', transport: 'socket'Thread[pool-1-thread-5,5,main]Thread[pool-1-thread-9,5,main]Thread[pool-1-thread-3,5,main]Thread[pool-1-thread-7,5,main]Thread[pool-1-thread-6,5,main]Thread[pool-1-thread-4,5,main]Thread[pool-1-thread-2,5,main]Thread[pool-1-thread-8,5,main]Thread[pool-1-thread-1,5,main]Disconnected from the target VM, address: '127.0.0.1:50402', transport: 'socket'
```

**颠覆常识的问题**

**Volatile是保证原子性还是可见性?**

这个问题我看资料总结过无数次,都说只能保证内存可见性,但是

volatile即内存屏障,可保证一段内存中一个变量的原子性,原生类型都是原子性的。所以java中  volatile long,volatile double都是线程安全的。

**为啥Automic  volatiel 用的是int   value?而不用boolean?**

```javascript
 volatile int scanState; volatile int  value;
```

因为在底层boolean的实现既是int实现的,所以volatile的set方法即安全的

**CAS锁是比较偏重的操作?**


CAS在操作锁时,执行比较并交换操作,相对synchronized瘦锁是比较重的锁,偏向锁在这里避免了CAS操作。UseBiaseLocking对synchronize有用

**总结:这期总结确实颠覆了以往认知,不管是以往的资料还是面试中很难去得到这样的知识点,当然仁者见仁,佩服的是小马哥对底层的理解,可手撕源码实现,这并非一朝一夕的能力,在平时中的书写也可模仿源码的操作,提高代码的可用性。**

**声明:本文内容根据B站UP主mercyblitz,往期视频以及历史资料整理,扫描二维码关注小马哥公众号,java劝退师,好东西需要分享,干货满满**
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。