Java多线程并发工具类

【JAVA 多线程】可见性 原子性 并发工具类 count++ 不是一个原子性操作, 他在执行的过程中,有可能被其他线程打断。 阅读详情

目录

 

AbstractQueuedSynchronizer

一、闭锁CountDownLatch

二、栅栏CyclicBarrier

三、信号量Semaphore

四、FutureTask

五、Exchanger


 

AbstractQueuedSynchronizer

是一个用于构建锁和同步器的框架;CountDownLatch、Semaphore、FutureTask都是基于AQS构建的。

 

一、闭锁CountDownLatch

简介:多个线程执行完后再执行下一步操作

举例:

class CountDownLatchUtils {
    private static final int count = 5;

    public static void main(String[] args) {

        final CountDownLatch countDownLatch = new CountDownLatch(count);
        final ExecutorService executorService = Executors.newFixedThreadPool(count);

        for (int i = 0; i < count; i++) {
            final int finalI = i;
            Future<?> future = executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        dosomething(finalI);
                        countDownLatch.countDown();//执行一次减小1
                        System.out.println(Thread.currentThread().getName()+" over");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        try {
            countDownLatch.await();//阻塞
            System.out.println("所有线程执行成功!!!dosomething...");

            executorService.shutdown();
            if(!executorService.awaitTermination(10*1000,TimeUnit.MILLISECONDS)){
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public static void dosomething(int i) throws InterruptedException {
        Thread.sleep((i+1)*2000);
        System.out.println(Thread.currentThread().getName()+"任务执行完成");
    }
}

二、栅栏CyclicBarrier

简介:

1、CyclicBarrier用于等待线程。可循环使用(Cyclic)的屏障(Barrier)。让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程继续干活。

2、与CountDownLatch不同的是该barrier在释放等待线程后可以重用

3、支持一个可选的Runnable命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次

举例:

class CyclicBarrierUtils {

    public static void main(String[] args) throws InterruptedException {

        ExecutorService consumerExe = Executors.newFixedThreadPool(2);
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
            @Override
            public void run() {
                System.out.println("栅栏打开!继续执行任务!");
            }
        });

        for (int i = 0; i < 4; i++) {
            final int finalI = i;
            consumerExe.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        dosomething(finalI);
                        int i = cyclicBarrier.await();
                        System.out.println(Thread.currentThread().getName() + "等待完成i;返回码:" + i);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }

                }
            });
        }

        consumerExe.shutdown();
        boolean flag = consumerExe.awaitTermination(10 * 1000, TimeUnit.MILLISECONDS);
        if (!flag) {
            consumerExe.shutdownNow();
        }


    }

    public static void dosomething(int i) throws InterruptedException {
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName() + "任务执行完成");
    }
}

三、信号量Semaphore

简介:

1、用于资源的多副本的并发访问控制,线程访问共享资源,先得到信号量。

若大于1表示共享资源可访问,信号量减去1在访问共享资源。如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之前进入休眠的线程将被唤醒并再次试图获得信号量。

内部维护了一个计数器,其值为可以访问的共享资源的个数。

例如:数据库连接池的实现

举例:4个碗筷,6个人吃饭

public class SemaphoreUtils {

    private final static Semaphore semaphore = new Semaphore(4);
    private final static ExecutorService produceExe = Executors.newCachedThreadPool();

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 6; i++) {
            produceExe.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        eat();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            });

        }
        produceExe.shutdown();
        produceExe.awaitTermination(10, TimeUnit.SECONDS);


    }

    public static void eat() throws InterruptedException {
        semaphore.acquire();
        System.out.println(Thread.currentThread().getName() + ":得到碗筷,开始吃饭");
        Thread.sleep(2000);
        semaphore.release();
        System.out.println(Thread.currentThread().getName() + ":释放碗筷。。。");
    }

}

四、FutureTask

简介:用于异步执行某个只执行一次的任务,可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务

public class FutrueTaskUtils {
    public static void main(String[] args) throws InterruptedException {

        FutureTask<String> futureTask =
                new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(5*1000);
                System.out.println("futureTask任务执行成功");
                return "SUCCESS";
            }
        });
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for(int i=0;i<4;i++){
            final int finalI = i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        dosomething(finalI);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });


            executorService.submit(futureTask);
        }

        try {
            System.out.println("futureTask任务,阻塞等待。。。");
            String str = futureTask.get();
            if("SUCCESS".equals(str)){
                System.out.println("futureTask任务完成");
                executorService.shutdown();
            }
            System.out.println(str);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }

    public static void dosomething(int i) throws InterruptedException {
        Thread.sleep((i+1)*2000);
        System.out.println(Thread.currentThread().getName()+"任务执行完成");
    }
}

 

五、Exchanger

简介:Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。

1、线程A调用Exchange对象的exchange()方法后,陷入阻塞状态。

2、直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据

3、线程A和B继续运行

举例:两个线程分别生产一根筷子,最后组合成一双

public class ExChangerUtils {
    public static void main(String[] args) {

        final int num = 10;

        final Exchanger<Chopsticks> exchanger = new Exchanger();

        final ConcurrentLinkedQueue<Chopsticks> dataQueue = new ConcurrentLinkedQueue();
        final ConcurrentLinkedQueue<Chopsticks> resultQueue = new ConcurrentLinkedQueue();

        for (int i = 0; i < num; i++) {
            Chopsticks chopsticks = new Chopsticks();
            dataQueue.offer(chopsticks);
        }

        ExecutorService producerExe1 = Executors.newSingleThreadExecutor();
        ExecutorService producerExe2 = Executors.newSingleThreadExecutor();

        producerExe1.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {

                    if (!dataQueue.isEmpty()) {
                        Chopsticks chopsticks = dataQueue.poll();
                        chopsticks.setChopstick1("chopstick1");
                        try {
                            Chopsticks changeChop = exchanger.exchange(chopsticks);
                            changeChop.setChopstick1("chopstick1");
                            if (!StringUtils.isBlank(changeChop.getChopstick2())) {
                                resultQueue.offer(changeChop);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        break;
                    }

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
                System.out.println("thread1 over");

            }
        });

        producerExe2.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (!dataQueue.isEmpty()) {
                        Chopsticks chopsticks = dataQueue.poll();
                        chopsticks.setChopstick2("chopstick2");
                        try {
                            Chopsticks changeChop = exchanger.exchange(chopsticks);
                            changeChop.setChopstick2("chopstick2");
                            if (!StringUtils.isBlank(changeChop.getChopstick1())) {
                                resultQueue.offer(changeChop);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        break;
                    }
                }
                System.out.println("thread2 over");
            }
        });

        new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (resultQueue.size() == num) {
                        for (Chopsticks chopsticks : resultQueue) {
                            System.out.println(chopsticks.toString());
                        }
                        break;
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }.run();


    }

    public static class Chopsticks {
        public String chopstick1;
        public String chopstick2;

        public String getChopstick1() {
            return chopstick1;
        }

        public void setChopstick1(String chopstick1) {
            this.chopstick1 = chopstick1;
        }

        public String getChopstick2() {
            return chopstick2;
        }

        public void setChopstick2(String chopstick2) {
            this.chopstick2 = chopstick2;
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer("Chopsticks{");
            sb.append("chopstick1='").append(chopstick1).append('\'');
            sb.append(", chopstick2='").append(chopstick2).append('\'');
            sb.append('}');
            return sb.toString();
        }
    }
}
Java并发工具类:构建高效多线程应用的关键!| 多线程篇(六) 🏆本文收录于「Java进阶实战」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 阅读详情

相关推荐

ISE 14.7 MCS文件的生成--- Spartan3AN XC3S200AN

步骤一: Generate Programming File生成 .bit文件 步骤二: Tools——>iMPCAT 步骤三: iMPACT Flows——>双击“Create PROM File(PROM File Formatter)” 步骤四: Non-Volatile FPGA——>点击”Spartan 3AN“——>点击“绿色箭头”——>Spartan3AN(bits)——>选择“xc3s200an"——>点击”Add storage Device“—

qq_40039676的博客 2100

java多线程常见工具类

CountDownLatch使用执行结果打印。

qq_50523945的博客 1873

瑞萨单片机,把CS文件转换为CC

1、打开CC的软件: 点击坐上角的"START" 点击"Create New Project"的"GO": 导入工程: 如下图设置后,点击"Create" 2、进入到CC的开发界面: 可以看到原启动库文件以asm文件的方式直接出现在工程中: 删除新生成的main.c,保留导入的r_main.c(以你自己的代码为准): 注意添加所有的头文件路径: 点击"...

weixin_37611121的博客 1228

java-多线程工具类(ConcurrentUtils)

在现代 Java 应用开发中,多线程编程是不可或缺的一部分,特别是在处理高并发、大规模数据处理、异步任务执行等场景时,良好的多线程管理是提高程序性能和响应速度的关键。然而,手动管理线程、线程池、同步机制等复杂的任务极易引发并发问题,如死锁、资源争用和线程饥饿等问题。因此,设计一个通用且高效的多线程工具类可以极大简化开发者在多线程编程中的工作。

Flying_Fish_roe的博客 1932

双足肌肉骨骼机器人

Clone Alpha的技术突破标志着人类进入生物-机械融合的新纪元,但其影响远超技术范畴。从伦理框架重建(如拉马克进化算法中的知识传递机制)到经济模式革新(如UBI应对机器人失业潮),需全球协作制定前瞻性政策。若放任技术无序扩张,人类社会或将面临“能力断层”与“控制权丧失”的双重危机;反之,若以人类福祉为核心导向,仿生机器人亦可成为弥合残障歧视、提升整体文明层级的钥匙。当下选择,将决定人类究竟是技术的创造者,还是被重构的客体。

百态·数智思维 | 聚焦大数据、量化与未来AI 985

Beyond the Spec: Decoding Samsung‘s LPDDR6 Sub-Channel and Wide-NRZ Innovations

本文深入解析了三星LPDDR6内存的两大核心技术:Sub-Channel架构与Wide-NRZ信号技术。Sub-Channel架构通过将物理通道划分为多个独立子通道,实现了内存访问的细粒度控制,大幅提升了能效,尤其适用于AI与边缘计算场景。Wide-NRZ则通过增加并行数据线而非采用PAM4,在提升带宽的同时保持了优异的信号完整性与低功耗特性。

weixin_29209801的博客 136

Java多线程工具CompletableFuture介绍

CompletableFuture是java.util.concurrent库在java 8中新增的主要工具,同传统的Future相比,其支持流式计算、函数式编程、完成通知、自定义异常处理等很多新的特性。

m0_38033199的博客 2073

给爸妈买的红米12C想装个老年桌面?先别急,解锁BL和Root前你得知道这些

本文详细解析了红米12C解锁BL和Root的利弊,为想要为长辈简化手机操作的用户提供全面指南。文章对比了BL解锁与Root的技术差异,推荐优先使用MIUI内置的极简模式等官方功能,并评估了Root的实际必要性。若必须Root,提供了安全操作流程和长期维护建议,帮助用户做出明智选择。

weixin_30265103的博客 318

Java多线程工具类

代码】Java多线程工具类。

一名在校大三学习JAVA 1453

Open3D 计算点云的倒角距离(Chamfer Distance)【2025最新版】

;Chamfer Distance距离可以计算生成点云数据与标签点云数据之间的平均最短点距离。Open3D可以直接用来计算点云的Chamfer Distance距离。博客长期更新,本文最近一次更新时间为:2025年2月18日。

点云侠的博客 3254

携程滑块、点选验证码登录识别逆向

本文分析了携程登录系统的风控机制,主要包含三种验证场景:无验证码、滑块验证码和二次图标点选验证码。通过跟踪risk_inspect风控接口,发现验证流程采用标准AES加密,需提交设备指纹等加密信息。当触发验证码时,需额外提交包含轨迹坐标的verify_msg参数及token/rid参数。最终通过风控检测后,需使用一致的指纹参数和验证token完成加密登录。文章强调所有分析仅用于学习,代码实现需确保符合法律规范。

码王吴彦祖的博客 1100

JAVA 多线程/并发

高并发、多线程 多线程 线程和进程 进程是程序的⼀次执⾏过程,系统资源分配的基本单位,线程是⼀个⽐进程更⼩的执⾏单位,CPU调度的基本单位,⼀个进程在其执⾏的过程中可以产⽣多个线程。 每个进程具有自己独立的地址空间,进程之间是相互独立的。 栈是线程私有的,堆是线程共享的.同类的多个线程共享进程的堆和⽅法区资源,但每个线程有⾃⼰的程序计数器、虚拟机栈和本地⽅法栈 进程上下文切换比线程开销大得多。 JAVA内存模型(JMM)  Java内存模式是一种虚拟机规范,JMM规范了Java虚拟机与计算机内存是如何协

qq_40860346的博客 614

某音私信接口二进制解析

本文探讨了某音私信接口的二进制请求处理过程,重点分析了请求体中的非文本字符和混合编码结构。文章详细描述了编码过程,包括使用Protocol Buffers的序列化方法将结构化数据转换为字节流,并通过Uint8Array包装成二进制数组。作者展示了如何提取和补全s.encode方法,并将其转化为Base64字符串以便在Python中解码执行

码王吴彦祖的博客 901

Java多线程—常用并发工具类

java多线程—常用并发工具类java多线程—常用并发工具类CountDownLatchCyclicBarrierReadWriteLockSemaphoreExchanger java多线程—常用并发工具类 CountDownLatch CountDownLatch 倒计时锁存器 CountDownLatch countDownLatch = new CountDownLatch(3); await(),进入等待的状态 countDown(),计数器减一 应用场景:启动三个线程计

ruan_luqingnian的博客 2313

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java中的并发工具类:让多线程编程更轻松

Java中的并发工具类:让多线程编程更轻松

m0_37825219的博客 514

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java 工具类_Java多线程并发工具类-信号量Semaphore对象讲解

Java多线程并发工具类-Semaphore对象讲解通过前面的学习,我们已经知道了Java多线程并发场景中使用比较多的两个工具类:做加法的CycliBarrier对象以及做减法的CountDownLatch对象并对这两个对象进行了比较。我们发现这两个对象要么是做加法,要么是做减法的。那么有没有既做加法也做减法的呢?当然有了。Semaphore这个工具类就可以实现One out one in的。本文...

weixin_39636609的博客 122

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java并发多线程 - 并发工具类JUC

...

WGH100817的博客 105

java对象转map工具类beanutils_Java多线程并发工具类-信号量Semaphore对象讲解

Java多线程并发工具类-Semaphore对象讲解通过前面的学习,我们已经知道了Java多线程并发场景中使用比较多的两个工具类:做加法的CycliBarrier对象以及做减法的CountDownLatch对象并对这两个对象进行了比较。我们发现这两个对象要么是做加法,要么是做减法的。那么有没有既做加法也做减法的呢?当然有了。Semaphore这个工具类就可以实现One out one in的。本文...

weixin_36050664的博客 193

Java多线程编程实战深入解析并发工具类及其应用场景

选择合适的并发工具依赖于具体的应用场景。对于简单的互斥,`synchronized`可能就足够了;对于复杂的同步流程,应选择`CountDownLatch`或`CyclicBarrier`;对于共享数据的并发访问,应优先考虑并发集合而非手动同步;对于管理大量异步任务,执行器框架是最佳实践。深入理解每个工具类的设计原理、优势与代价,是构建高性能、高可靠性Java并发应用的关键。通过合理运用这些工具,开发者可以有效地规避竞态条件、死锁、活锁等并发陷阱,充分发挥多核处理器的计算能力。

ayuzy07的博客 470

Java多线程常用的并发工具类

CyclicBarrier:一组线程互相等待,到达barrier节点后继续运行。1、创建线程:通过继承Thread类或者调用Runnable接口。CountDownLatch:计数锁存器,协调线程之间的同步。Semaphore:信号量,控制同时运行的线程数。Executors:用于创建和管理线程。

qq_73483274的博客 174

【死锁预防策略】深入浅出Java多线程编程:从基础到最佳实践并发工具类实战

建议从简单场景入手,逐步深入理解JMM内存模型、happens-before原则等底层机制。持续关注Java并发API的更新(如Project Loom的虚拟线程),根据实际场景选择合适的并发模型。记住:不要为了并发而并发,正确的设计比盲目使用多线程更重要。学习教程(传送门)1、掌握JAVA入门到进阶知识(持续写作中……2、学会Oracle数据库用法(创作中……3、手把手教你vbs脚本制作(完善中……4、牛逼哄哄的IDEA编程利器(编写中……5、吐血整理的面试技巧(

王大师企业官方博客 1894

Java并发编程实战:多线程、锁与并发工具类详解

在Java中,并发编程是处理多个任务同时执行的一种重要方式。Java并发工具包(java.util.concurrent,简称JUC)在Java 5版本中被引入,提供了大量实用的工具类,用于多线程编程中的线程同步、协调和并发控制。下面将详细探讨Java并发编程中的多线程、锁以及并发工具类的使用。

LindsayLucius的博客 587

Java中有关多线程并发的几个工具类之总结

概述 在JDK的并发包(java.util.concurrent)中,为我们提供了几个非常重要的并发工具类,分别为CountDownLatch、CyclicBarrier、Semaphore和Exchanger,下面将一一对这几个类的功能及基本用法做详细讲解。 1)CountDownLatch CountDownLatch,类似于计数器的方式,用于等待一个或多个线程执行完操作开始自身代码的执...

u010349644的专栏 6607

探索Java多线程编程深入解析并发工具类与实战应用

同时,要重视线程池的监控和调优,避免任务堆积和资源耗尽。ConcurrentHashMap采用分段锁技术,将数据分段存储,不同段的数据可以被不同的线程同时访问,既保证了线程安全又提供了高并发性能。CopyOnWriteArrayList则通过在修改操作时创建底层数组的新副本来实现线程安全,适合读多写少的场景,但写操作的开销较大。为了应对这些挑战,Java在java.util.concurrent包中提供了丰富的并发工具类,这些工具类不仅简化了多线程编程的复杂度,还大大提升了程序的可靠性和执行效率。

SPM613110的博客 365

Java多线程-3-并发容器和工具类

Java并发容器和工具类

loetca 246

Java多线程编程实战深入解析并发工具类与性能优化策略

Java并发工具类提供了构建高性能多线程应用的坚实基础。开发者需根据具体场景选择合适的工具和策略,通过线程池调优、锁优化和无锁编程提升系统并发能力。持续的性能监控和诊断是保证系统稳定运行的必要手段。深入理解这些工具和策略,将显著提升Java应用的性能和可扩展性。

Kuriyama的博客 527
上一篇: Java线程池的使用
下一篇: Java多线程基础
九号铅笔芯
博客等级 码龄9年 9粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值