首页 > 编程语言 >JAVA并发工具类

JAVA并发工具类

时间:2024-07-02 23:55:17浏览次数:12  
标签:JAVA Thread System 并发 线程 println 工具 CyclicBarrier out

JAVA中并发工具类CountDownLatch、CyclicBarrier和Semaphore的概念和使用。

一、CountDownLatch(计数器)

  CountDownLatch的应用场景是某个线程任务需要等待其他的线程全部执行完毕才能执行,这时候就可以使用CountDownLatch类。其内部使用计数器实现,计数器的初始值为线程的数量,可以在构造对象时传入。之后每个线程调用其countDown()方法,计数器的值就会减一。而当计数器初始值到达0时,表示所有的线程已经完成了任务。因此之前因为调用await()方法而等待的线程就可以恢复执行任务。

import java.util.concurrent.CountDownLatch;
public class Main {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(2);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ", begin...");
            cdl.countDown();
            System.out.println(Thread.currentThread().getName() + ", end...");
        }).start();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ", begin...");
            cdl.countDown();
            System.out.println(Thread.currentThread().getName() + ", end...");
        }).start();
        //只有调用了两次countDown方法,计数器值才变为0。此时当前线程才被唤醒继续执行
        cdl.await();
        System.out.println("两个Thread执行完毕.....");
        System.out.println("主线程继续执行");
        for (int i = 0; i < 10; i ++) {
            System.out.println(Thread.currentThread().getName() + ", i:" + i);
        }
    }

}

二、CyclicBarrier(屏障)

  CyclicBarrier初始化时同样也规定一个数目,然后计算调用其await()而进入等待的线程数。CyclicBarrier可看成是个障碍,所有的线程调用await()方法就被阻塞且线程数量加1,当被阻塞的线程数量达到规定的数目。说明指定数量的线程均匀执行到调用await()的位置,此时再全部放行往下执行。即所有线程必须到齐才能一起通过这个障碍。另外CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目到达后,所有其他线程被唤醒前执行。

import java.util.concurrent.CyclicBarrier;
public class Main {

    public static void main(String[] args) {
        CyclicBarrier cbr = new CyclicBarrier(5);
        for (int i = 0; i < 5; i ++) {
            Writer writer = new Writer(cbr);
            writer.start();
        }
    }

}

class Writer extends Thread {

    private CyclicBarrier cbr;

    public Writer(CyclicBarrier cbr) {
        this.cbr = cbr;
    }

    @Override
    public void run() {
        try {
            System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据");
            Thread.sleep(3000);
            System.out.println("线程" + Thread.currentThread().getName() + "写入成功");
            //这里只有5个线程都调用await方法,才会往下执行,因此相当于屏障
            cbr.await();
            System.out.println("所有线程执行完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、Semaphore(计数信号量)

  Semaphore是一种基于计数的信号量,它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。因此Semaphore可以用来构建一些对象池、资源池之类的,比如数据库连接池。也可以创建计数为1的Semaphore实现互斥锁的机制,也叫做二元信号量。使用Semaphore类时,其availablePermits()方法可以获取当前可用的资源数量。acquire()申请信号量资源,无资源可用时会阻塞当前线程、release()释放当前获取的资源。其中acquire()和release()默认都是参数为1,也可传入int参数申请指定数量的资源。

import java.util.concurrent.Semaphore;
public class Main {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(4);
        for (int i = 1; i <= 10; i ++) {
            UserThread userThread = new UserThread("用户" + i + "号", semaphore);
            userThread.start();
        }
    }

}

class UserThread extends Thread {

    private String name;
    private Semaphore jsShop;

    public UserThread(String name, Semaphore jsShop) {
        this.name = name;
        this.jsShop = jsShop;
    }

    @Override
    public void run() {
        try {
            jsShop.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "得到服务");
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(name + "服务结束");
        jsShop.release();
    }
}

标签:JAVA,Thread,System,并发,线程,println,工具,CyclicBarrier,out
From: https://www.cnblogs.com/idempotent/p/12391061.html

相关文章

  • JAVA并发知识
    JAVA常见的并发知识点,概念和使用方法。一、Synchronized和Lock的区别Synchronized:Synchronized是Java提供的关键字,可以在需要同步的对象中加入此控制。其可以用来修辞方法,也可以加在特定代码块中,而修辞特定代码块时括号中表示需要锁的对象。JVM底层实现:  Synchronized......
  • JAVA文件IO流
    基本的目录、文件操作,常用的IO输入输出流类介绍和使用。一、目录及文件操作Java中File类(文件类)以抽象的方式代表文件名和目录路径名,File对象则代表了磁盘中实际存在的文件和目录。  File类不仅仅提供灵活的构造方法,同时还可以用于文件和目录的创建、文件的查找和文件的......
  • 维克日记 v0.4.2:开发者友好的数字化笔记工具
     维克日记,专为技术开发者和笔记爱好者设计的数字化笔记工具,以其强大的功能和灵活的配置赢得了用户的好评。软件采用Markdown语法,提供实时预览功能,让您的笔记编辑更加高效和直观。维克日记的用户界面简洁而功能齐全,无需复杂的设置,即可开始记录您的思路和创意。它支持表格可视化......
  • 学习java第一百一十八天
    @Component和@Bean的区别是什么?@Component注解作用于类,而@Bean注解作用于方法。@Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径从中找出标识了需要装配的类自动装配到Spring的bean容器中)。@B......
  • java的序列化和反序列化
    一、概念序列化是将对象的常态存储到特定的存储介质中的过程。反序列化是将特定的存储介质中的数据重新构建对象的过程。问题为每个对象属性——编写读写代码,过程很繁琐且非常容易出错,如何解决? 二、使用ObjectOutputStream类实现序列化a.序列化的对象所属类必须为可......
  • java07
    数组数组的声明和创建dataType[]=arrayRefVar创建数组dataType[]arrayRefVar=newdataType[array.length];数组长度arrays.length内存堆:1,存放new的对象和数组2,栈:1,存放基本的变量类型2,引用对象的变量数组的注意事项1.数组一旦被创建,长度就是确定的2.其元素必须......
  • 从零开始学习Java的第五天
    掌握数组的定义数组:用来存储一批同种类型数据的容器遇到批量数据的存储和操作时,用数组比用变量更适合了解静态初始化数组数据类型[] 数组名=new数据类型[]{元素1,元素2,元素3,......}简化写法:数据类型[] 数组名={元素1,元素2,元素3,......}数据类型[] ......
  • 从零开始学习Java的第三天
    掌握switch语句的用法switch语句具有穿透性,所以语句间要加上break循环语句的组成:初始化语句:循环开始时候什么样条件判断语句:循环是否能一直执行下去循环体语句:循环反复执行的事情条件控制语句:控制循环是否能执行下去循环结构对应的语法:初始化语句:这里可以是一条或多条......
  • java中处理字符串常用的api
    Java中String常用APIString类位于jdk中的java.lang.String包中publicintlength()获取字符串的长度(字符的个数)publiccharcharAt(intindex)获取某个索引位置的字符返回publicchar[]t......
  • 【Java学习笔记】方法的使用
    【Java学习笔记】方法的使用一、一个例子二、方法的概念及使用(一)什么是方法(二)方法的定义(三)方法调用的执行过程(四)实参和形参的关系(重要)(五)没有返回值的方法三、方法重载(一)为什么需要方法重载(二)方法重载概念(三)方法签名四、递归(一)生活中的故事(二)递归的概念(三)递归执行过程分......