• java并发包工具(java.util.Concurrent)


    一、CyclicBarrier

    作用:所有线程准备好才进行,只要一条线程没准备好,都不进行

    用法:所有线程准备好以后调用CyclicBarrier的await方法,然后主线程执行CyclicBarrier的countDown方法

    实现需求:n个运动员(n个线程),全部准备好了才一起起跑。代码如下

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

    二、CountDownLacth

    作用:监听某些初始化操作,等初始化执行完毕以后,通知主线程继续工作(例如zk的初始化)

    用法:将需要别的线程来通知的线程调用CountDownLacth的await方法,其他线程执行了之后,允许这个线程执行的时候,执行CountDownLacth的countDown方法

    实现需求:启动3个线程,1线程等待2和3线程执行完毕以后再执行,代码如下:

     1 package concurrent019;
     2 
     3 import java.util.concurrent.CountDownLatch;
     4 
     5 public class UseCountDownLatch {
     6 
     7     public static void main(String[] args) {
     8         
     9         final CountDownLatch countDown = new CountDownLatch(2);
    10         
    11         Thread t1 = new Thread(new Runnable() {
    12             @Override
    13             public void run() {
    14                 try {
    15                     System.out.println("进入线程t1" + "等待其他线程处理完成...");
    16                     countDown.await();
    17                     System.out.println("t1线程继续执行...");
    18                 } catch (InterruptedException e) {
    19                     e.printStackTrace();
    20                 }
    21             }
    22         },"t1");
    23         
    24         Thread t2 = new Thread(new Runnable() {
    25             @Override
    26             public void run() {
    27                 try {
    28                     System.out.println("t2线程进行初始化操作...");
    29                     Thread.sleep(3000);
    30                     System.out.println("t2线程初始化完毕,通知t1线程继续...");
    31                     countDown.countDown();
    32                 } catch (InterruptedException e) {
    33                     e.printStackTrace();
    34                 }
    35             }
    36         });
    37         Thread t3 = new Thread(new Runnable() {
    38             @Override
    39             public void run() {
    40                 try {
    41                     System.out.println("t3线程进行初始化操作...");
    42                     Thread.sleep(4000);
    43                     System.out.println("t3线程初始化完毕,通知t1线程继续...");
    44                     countDown.countDown();
    45                 } catch (InterruptedException e) {
    46                     e.printStackTrace();
    47                 }
    48             }
    49         });
    50         
    51         t1.start();
    52         t2.start();
    53         t3.start();
    54         
    55     }
    56 }

    ps:CyclicBarrier和CountDownLacth的区别

    CyclicBarrier是所有线程等待一个线程的信号,CountDownLacth是一个线程等待所有线程的信号

    三、Callable、Future

    Future实现的就是前面讲的Future模式.

    实现功能:主线程在执行的过程中,调用了一个或者多个耗时的操作,需要把这个耗时的操作提到另几个线程操作(这几个耗时的操作可以并行执行)

    代码实现:

     1 package concurrent019;
     2 
     3 import java.util.concurrent.Callable;
     4 import java.util.concurrent.ExecutorService;
     5 import java.util.concurrent.Executors;
     6 import java.util.concurrent.FutureTask;
     7 
     8 public class UseFuture implements Callable<String>{
     9     private String para;
    10     
    11     public UseFuture(String para){
    12         this.para = para;
    13     }
    14     
    15     /**
    16      * 这里是真实的业务逻辑,其执行可能很慢
    17      */
    18     @Override
    19     public String call() throws Exception {
    20         //模拟执行耗时
    21         Thread.sleep(3000);
    22         String result = this.para + "处理完成";
    23         return result;
    24     }
    25     
    26     //主控制函数
    27     public static void main(String[] args) throws Exception {
    28         String queryStr = "query";
    29         //构造FutureTask,并且传入需要真正进行业务逻辑处理的类,该类一定是实现了Callable接口的类
    30         FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr));
    31         //创建一个固定线程的线程池且线程数为1,
    32         ExecutorService executor = Executors.newFixedThreadPool(1);
    33         //这里提交任务future,则开启线程执行RealData的call()方法执行
    34         executor.submit(future);
    35         System.out.println("请求完毕");
    36         try {
    37             //这里可以做额外的数据操作,也就是主程序执行其他业务逻辑
    38             Thread.sleep(2000);
    39         } catch (Exception e) {
    40             e.printStackTrace();
    41         }
    42         //调用获取数据方法,如果call()方法没有执行完成,则依然会进行等待
    43         System.out.println("数据:" + future.get()); // 其实这块应该开启线程处理
    44         executor.shutdown();
    45     }
    46 
    47 }

    四、Semaphore(信号量)

    Semaphore是计数信号量。Semaphore管理一系列许可证。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法。然而,其实并没有实际的许可证这个对象,Semaphore只是维持了一个可获得许可证的数量。(用于限流)

    实现需求:总共有20条线程,但是最多只能放5条线程进来执行

    代码实例:

     1 package concurrent019;
     2 
     3 import java.util.concurrent.ExecutorService;  
     4 import java.util.concurrent.Executors;  
     5 import java.util.concurrent.Semaphore;  
     6   
     7 public class UseSemaphore {  
     8   
     9     public static void main(String[] args) {  
    10         // 线程池  
    11         ExecutorService exec = Executors.newCachedThreadPool();  
    12         // 只能5个线程同时访问  
    13         final Semaphore semp = new Semaphore(5);  
    14         // 模拟20个客户端访问  
    15         for (int index = 0; index < 20; index++) {  
    16             final int NO = index;  
    17             Runnable run = new Runnable() {  
    18                 public void run() {  
    19                     try {  
    20                         // 获取许可  
    21                         semp.acquire();  
    22                         System.out.println("Accessing: " + NO);  
    23                         //模拟实际业务逻辑
    24                         Thread.sleep((long) (Math.random() * 10000));  
    25                         // 访问完后,释放  
    26                         semp.release();  
    27                     } catch (InterruptedException e) {  
    28                     }  
    29                 }  
    30             };  
    31             exec.execute(run);  
    32         } 
    33         
    34         try {
    35             Thread.sleep(10);
    36         } catch (InterruptedException e) {
    37             e.printStackTrace();
    38         }
    39         
    40         //System.out.println(semp.getQueueLength());
    41         
    42         
    43         
    44         // 退出线程池  
    45         exec.shutdown();  
    46     }  
    47   
    48 }  
  • 相关阅读:
    一对一关联
    一对多关联
    软删除
    分层控制器
    系统的助手函数
    tp5命令行基础介绍
    PHP 开启跨域
    生成数据库模型文件
    REST API 安全设计指南
    jquery-Ajax请求用例码
  • 原文地址:https://www.cnblogs.com/billmiao/p/9872202.html
Copyright © 2020-2023  润新知