zoukankan      html  css  js  c++  java
  • java架构《并发线程高级篇三》

        本章主要介绍和讲解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%的时间内达到。         

  • 相关阅读:
    Linux压缩和解压类指令
    Linux 搜索查找类指令
    Linux时间日期类指令
    Linux文件目录类指令
    Linux帮助指令
    Linux运行级别
    微信授权获取code/openid
    微信公众配置
    MySQL规范
    PHP7搭建项目遇到的坑
  • 原文地址:https://www.cnblogs.com/coes/p/6862762.html
Copyright © 2011-2022 走看看