本章主要介绍和讲解concurrent.util里面的常用的工具类。

一、CountDownLatch使用:(用于阻塞主线程)

      应用场景 :通知线程休眠和运行的工具类,是wait和notify的升级版本。notify不会释放锁,但是  countDown()会释放锁

         

                      实例化:final CountDownLatch countDown = new CountDownLatch(2);

                  使用在Thread里面:   countDownLatch.countDown(); 相当于 notfiy;  特点: countDown()会释放锁
countDownLatch.await();相当于 wait;

二、CyclicBarrier使用:barrier(障碍) (用于多个阻塞线程等待,都通准备好后,一起开始执行当前线程的代码)

      应用场景:多个线程,当任何一个线程都没准备好,都阻塞。当都准备好时,都执行自己的线程。

      注意事项:多少个线程,需要多少个barrier.await();否则都会阻塞在此。

      代码解析:

          

          

 1                public class UseCyclicBarrier {
2
3             static class Runner implements Runnable {
4             private CyclicBarrier barrier;
5             private String name;
6
7             public Runner(CyclicBarrier barrier, String name) {
8               this.barrier = barrier;
9               this.name = name;
10               }
11             @Override
12             public void run() {
13               try {
14                 Thread.sleep(1000 * (new Random()).nextInt(5));
15                 System.out.println(name + " 准备OK.");
16                 barrier.await();
17                 } catch (InterruptedException e) {
18                   e.printStackTrace();
19                 } catch (BrokenBarrierException e) {
20                   e.printStackTrace();
21                 }
22                 System.out.println(name + " Go!!");
23                 }
24               }
25
26         public static void main(String[] args) throws IOException, InterruptedException {
27             CyclicBarrier barrier = new CyclicBarrier(3); // 3
28             ExecutorService executor = Executors.newFixedThreadPool(3);
29
30             executor.submit(new Thread(new Runner(barrier, "zhangsan")));
31             executor.submit(new Thread(new Runner(barrier, "lisi")));
32             executor.submit(new Thread(new Runner(barrier, "wangwu")));
33
34             executor.shutdown();
35           }
36
37         }

三、Future模式补充和Callable

         使用场景:需要大数量量处理数据的时候,异步去处理数据,提高程序的吞吐量

           注意事项:真正进行业务逻辑处理的类, 类一定实现Callable接口,重写Call()方法。

         

 1         private String para;
2
3           public UseFuture(String para){
4           this.para = para;
5           }
6
7           /**
8           * 这里是真实的业务逻辑,其执行可能很慢
9           */
10           @Override
11           public String call() throws Exception {
12           //模拟执行耗时
13           Thread.sleep(5000);
14           String result = this.para + "处理完成";
15           return result;
16         }
17
18        
19
20         String queryStr = "query";
21         //构造FutureTask,并且传入需要真正进行业务逻辑处理的类,该类一定是实现了Callable接口的类
22         FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr));
23
24         FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr));
25         //创建一个固定线程的线程池且线程数为1,
26         ExecutorService executor = Executors.newFixedThreadPool(2);
27         //这里提交任务future,则开启线程执行RealData的call()方法执行
28         //submit和execute的区别: 第一点是submit可以传入实现Callable接口的实例对象, 第二点是submit方法有返回值
29
30         Future f1 = executor.submit(future); //单独启动一个线程去执行的
31         Future f2 = executor.submit(future2);
32         System.out.println("请求完毕");
33
34           try {
35             //这里可以做额外的数据操作,也就是主程序执行其他业务逻辑
36             System.out.println("处理实际的业务逻辑...");
37             Thread.sleep(1000);
38           } catch (Exception e) {
39               e.printStackTrace();
40             }
41           //调用获取数据方法,如果call()方法没有执行完成,则依然会进行等待
42           System.out.println("数据:" + future.get());
43           System.out.println("数据:" + future2.get());
44
45           executor.shutdown();

        

        总结:FutureTask对象。当使用其get()方法时,会异步加载对应的返回结果。Future 对象。当使用其get()方法时。返回null,则表示该子线程已经完成。

           submit和execute的区别: 第一点是submit可以传入实现Callable接口的实例对象, 第二点是submit方法有返回值。

四、Semaphore信号量

        使用场景:当 系统上线之前,对系统进行信息并发量的评估。进行自动化测试。在业务逻辑层,进行限流

        相关概念:

            

                     PV(page  view) :网站总访问量,页面浏览量或点击量,每刷新一次都记录下来。

             UV(unique Visitor):访问网站的IP总数,没一个Ip,一天内只记录一次。
             QRS(Query per second):每秒的查询数。              RT(response time):访问相应时间。

        

        代码解析:

            创建一个无界阻塞的线程池。通过循环产生多个线程。每个线程里面进行业务逻辑实现。每次实现业务前。都获得semp.acquire()(许可),完成之后,都semp.release()(释放许可),做到限流。

        用法:    

          

 1               // 只能5个线程同时访问
2           final Semaphore semp = new Semaphore(5);
3
4           // 获取许可
5
6           semp.acquire();
7           System.out.println("Accessing: " + NO);
8           //模拟实际业务逻辑
9           Thread.sleep((long) (Math.random() * 10000));
10           // 访问完后,释放
11           semp.release();

        峰值计算:    

               峰值qp:(总PV*80%)/(60*60*24*20%)

             80%的访问请求将在20%的时间内达到。         

java架构《并发线程高级篇三》的更多相关文章

  1. java架构《并发线程高级篇四》

    本章主要讲并发线程的常见的两种锁.重入锁和读写锁 一:重入锁(ReentrantLock) 概念:重入锁,在需要进行同步的代码加锁,但最后一定不要忘记释放锁,否则会造成锁永远不能释放,其他线程进不了 ...

  2. java架构《并发线程高级篇一》

    本章主要记录讲解并发线程的线程池.java.util.concurrent工具包里面的工具类. 一:Executor框架: Executors创建线程池的方法: newFixedThreadPool( ...

  3. java架构《并发线程高级篇二》

    本章主要记录讲解并发线程的线程池.使用Executor框架自定义线程池. 自定义线程池使用Queue队列所表示出来的形式: 1 ArrayBlockingQueue<Runnable>(3 ...

  4. Java高并发 -- 线程池

    Java高并发 -- 线程池 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 在使用线程池后,创建线程变成了从线程池里获得空闲线程,关闭线程变成了将线程归坏给线程池. ...

  5. Java高并发--线程安全策略

    Java高并发--线程安全策略 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 不可变对象 发布不可变对象可保证线程安全. 实现不可变对象有哪些要注意的地方?比如JDK ...

  6. Java并发-线程池篇-附场景分析

    作者:汤圆 个人博客:javalover.cc 前言 前面我们在创建线程时,都是直接new Thread(): 这样短期来看是没有问题的,但是一旦业务量增长,线程数过多,就有可能导致内存异常OOM,C ...

  7. Java高并发与多线程(四)-----锁

    今天,我们开始Java高并发与多线程的第四篇,锁. 之前的三篇,基本上都是在讲一些概念性和基础性的东西,东西有点零碎,但是像文科科目一样,记住就好了. 但是本篇是高并发里面真正的基石,需要大量的理解和 ...

  8. Java之创建线程的方式四:使用线程池

    import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.c ...

  9. java架构《并发线程中级篇》

    java多线程的三大设计模式 本章主要记录java常见的三大设计模式,Future.Master-Worker和生产者-消费者模式. 一.Future模式 使用场景:数据可以不及时返回,到下一次实际要 ...

随机推荐

  1. dp的冗余(选数类)

    我们先来看一个例题: 在一个长度为n的序列中选出任意个数的数,要求每m个数中至少一个被选,要求选的数之和最小化. 我们很容易想出用f[i][j]来表示前i个数选的最后一个数是j,也就有 for(int ...

  2. OpenSUSE 使用基础

    OpenSUSE OpenSUSE 是一个基于 RPM 的发行版,这和 RHEL/CentOS 一致. 但是它的官方包管理器是专有的 zypper,挺好用的,软件也很新. 本文以 OpenSUSE L ...

  3. 1001 害死人不偿命的(3n+1)猜想 (15分)

    卡拉兹(Callatz)猜想: 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把 (3n+1) 砍掉一半.这样一直反复砍下去,最后一定在某一步得到 n=1.卡拉兹在 1950 ...

  4. spark的运行指标监控

    sparkUi的4040界面已经有了运行监控指标,为什么我们还要自定义存入redis? 1.结合自己的业务,可以将监控页面集成到自己的数据平台内,方便问题查找,邮件告警 2.可以在sparkUi的基础 ...

  5. 对接口报错404 发现url多了一些不可描述的代码%E2%80%8B

    接口url出现了空格,复制的url可能出现空格肉眼看不出来,手动输入一遍URL

  6. Liunx运维(十一)-系统管理命令

    文档目录: 一.lsof:查看进程打开的文件 二.uptime:显示系统的运行时间及负载 三.free:查看系统内存信息 四.iftop:动态显示网络接口流量信息 五.vmstat:虚拟内存统计 六. ...

  7. 容器编排系统K8s之节点污点和pod容忍度

    前文我们了解了k8s上的kube-scheduler的工作方式,以及pod调度策略的定义:回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14243312.ht ...

  8. CentOS7 普通用户绕过root登录

      正常环境中我们的服务器都会使用一个普通用户跳转到root进行操作,如果root用户的密码不记得只知道普通用户密码,设备又不方便进行开关机破密码时,我们就可以用到以下方法登陆设备. pkexec : ...

  9. [从源码学设计]蚂蚁金服SOFARegistry 之 ChangeNotifier

    [从源码学设计]蚂蚁金服SOFARegistry 之 ChangeNotifier 目录 [从源码学设计]蚂蚁金服SOFARegistry 之 ChangeNotifier 0x00 摘要 0x01 ...

  10. 如何使用 VS Code开发.NET Core应用程序

    Visual Studio Code(VS Code)是Microsoft为Windows,Linux和Mac操作系统开发的免费,跨平台,轻量级的源代码编辑器,它是源代码编辑器,而Visual Stu ...