Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >多线程顺序处理的方式多线程顺序处理的方式

多线程顺序处理的方式多线程顺序处理的方式

作者头像
名字是乱打的
发布于 2021-12-24 00:47:55
发布于 2021-12-24 00:47:55
39000
代码可运行
举报
文章被收录于专栏:软件工程软件工程
运行总次数:0
代码可运行

目前有个任务需要对数据进行一个循环处理,那么就需要多线程顺序触发的问题了. 这里以顺序打印为例子对常见的多线程顺序处理做个总结,拿出两个非常常用的方式.

方法一: 资源+锁

核心点: 1.锁共同资源lock 2.通过while循环判断每次被唤醒是否要再次阻塞

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ThreadsPrintOrder {
    private static Integer curr = 0;
    private static String[] strs = new String[]{"A", "B", "C"};
    private static int count = 10;
    static  Object lock=new Object();

    public static void main(String[] args) {
        final Thread a = getThread("A");
        final Thread b = getThread("B");
        final Thread c = getThread("C");

        a.start();
        b.start();
        c.start();
    }

    private static Thread getThread(String threadName) {
        return new Thread(() -> {
            synchronized (lock) {
                for (int i = 0; i < count; i++) {
                    while (!strs[curr%strs.length].equals(threadName)) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName());
                    curr++;
                    lock.notifyAll();
                }
            }
        }, threadName);
    }
}

方法二 一个ReentrantLock加多个conditon实现(推荐,安全性,性能和可读性较高)

上面那种方法有个缺点就是每个线程被唤醒是随机的,每次被唤醒的可能是我们不想打印的线程,需要它再次自我关闭. 而ReentrantLock的独特效果可以做到结合conditon实现定向唤醒.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ThreadsPrintOrder_m2 {
    static int count=10;
    public static void main(String[] args) {
        LockOrderPrint lockOrder=new LockOrderPrint();
        new Thread(()->{
            for (int i = 0; i <count ; i++) {
                lockOrder.printA();
            }
        }).start();

        new Thread(()->{
            for (int i = 0; i <count ; i++) {
                lockOrder.printB();
            }
        }).start();

        new Thread(()->{
            for (int i = 0; i <count ; i++) {
                lockOrder.printC();
            }
        }).start();
    }
}

class LockOrderPrint {
    int flag=0;
    Lock lock=new ReentrantLock();
    Condition conditionA=lock.newCondition();
    Condition conditionB=lock.newCondition();
    Condition conditionC=lock.newCondition();

    public void printA(){
        lock.lock();
        try {
            while (flag%3!=0){
                try {
                    conditionA.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("A");
            flag++;
            conditionB.signal();

        }catch (Exception exce){
            exce.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void printB(){
        lock.lock();
        try {
            while (flag%3!=1){
                try {
                    conditionB.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("B");
            flag++;
            conditionC.signal();
        }catch (Exception exce){
            exce.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void printC(){
        lock.lock();
        try {
            while (flag%3!=2){
                try {
                    conditionC.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("C");
            flag++;
            conditionA.signal();
        }catch (Exception exce){
            exce.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/9/7 下午,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock。 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍ReentrantLock。 锁是什么? 并发编程的时候,比如说有一个业务是读写操作,那多个线程执行这个业务就会造成已经写入的数据又写一遍,就会造成数据错乱。 所以需要引入锁,进行数据同步,强制使得该业务执行的时候只有一个线程在执行,从而保证不会插入多条重复数据。 一些共享资源也是需要加锁,从而保证数据的一致性。
Janti
2018/04/10
8610
Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
JUC系列(一) 多线程基础复习
对于Java 而言创建线程我们学习到的方法有三种 : Thread , Runnable , Callable
冷环渊
2022/10/04
2520
JUC系列(一) 多线程基础复习
Java并发编程(06):Lock机制下API用法详解
Lock加锁相关结构中涉及两个使用广泛的基础API:ReentrantLock类和Condition接口,基本关系如下:
知了一笑
2020/07/09
3640
Java并发编程(06):Lock机制下API用法详解
多线程笔记(九)线程之间的通信
我们多个线程之间通信,有wait() notify(),notifyall()方法,但是wait()方法是在哪里睡,之后被唤醒的时候就在哪里醒来,所以我们的wait()方法是不能在if里面,使用while,当唤醒的时候,会重新判断条件,if是不会判断的;
一写代码就开心
2022/05/25
3010
多线程笔记(九)线程之间的通信
面试题:三个线程按顺序打印 ABCABC
线程 A 先拿到资源 c,再拿资源 a ,[a 执行完后释放,并唤醒等待资源 a] 的 线程 B 线程 B 先拿到资源 a,再拿资源 b ,[b 执行完后释放,并唤醒等待资源 b] 的 线程 C 线程 C 先拿到资源 b,再拿资源 c ,[c 执行完后释放,并唤醒等待资源 c] 的 线程 A
码哥字节
2024/05/17
6200
面试题:三个线程按顺序打印 ABCABC
58面试官居然问我Synchronized底层实现,锁升级的具体过程?
这是我去年7,8月份面58被问的一个面试题,说实话被问到这个问题还是很意外的,感觉这个东西没啥用啊,直到后面被问了一波new Object,Integer对象等作为加锁对象行吗?会出现哪些问题?为啥java6后synchronized性能大幅上升?我彻底蒙蔽了。下面详细总结一下
Java识堂
2020/02/19
7901
多线程 - 生产者消费者模式
通过生产者消费者模式的编写,可以了解线程间的通信问题,通过condition的signal和await进行唤醒和等待比wait和notify更好,因为signal和await可以针对特定的线程进行唤醒和等待,比notifyAll更安全。
承苏凯
2020/07/24
4440
多线程 - 生产者消费者模式
Java多线程学习(六)Lock锁的使用
我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailclimb/Java-Guide
用户2164320
2018/06/23
11.4K0
Java多线程学习(六)Lock锁的使用
Condition控制线程通信:java三个线程循环打印ABC
private Lock lock = new ReentrantLock(); private Condition c1 = lock.newCondition(); private Condition c2 = lock.newCondition(); private Condition c3 = lock.newCondition(); private int remark = 1;// public static void main(String[] args) throws Inter
用户1215919
2018/02/27
1.2K0
Java多线程学习(六)——Lock的使用
锁是用于通过多个线程控制对共享资源的访问的工具。通常,锁提供对共享资源的独占访问:一次只能有一个线程可以获取锁,并且对共享资源的所有访问都要求首先获取锁。 但是,一些锁可能允许并发访问共享资源,如ReadWriteLock的读写锁。Java5之后并发包中新增了Lock接口以及相关实现类来实现锁功能。
小森啦啦啦
2019/09/17
4830
Lock介绍
java.util.concurrent.locks包下常用的类与接口(lock是jdk 1.5后新增的)。
HLee
2021/10/09
8210
Lock介绍
java多线程编程核心技术——第四章总结
本文介绍了多线程中锁的深入解析,通过锁的底层原理、使用方式、性能优化等方面进行展开,并结合具体代码案例,让读者深入理解锁的底层原理和实际应用。
用户1134788
2018/01/05
7820
Thread和goroutine两种方式实现共享变量按序输出
最近在看go的一些底层实现,其中印象最为深刻的是go语言创造者之一Rob Pike说过的一句话,不要通过共享内存通信,而应该通过通信来共享内存,其中这后半句话对应的实现是通道(channel),利用通道在多个协程(goroutine)之间传递数据。看到这里,我不禁产生了一个疑问,对于无状态数据之间的传递,通过通道保证数据之间并发安全没什么问题,但我现在有一个临界区或者共享变量,存在多线程并发访问。Go协程如何控制数据并发安全性?难道还有其它高招?带着这个疑问,我们看看Go是如何保证临界区共享变量并发访问问题。
用户5166556
2020/09/15
8140
Java多线程04——线程通信
线程是操作系统中的独立个体,但这些个体如果不经过特殊处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。例如之前处理的线程同步,就是一种线程间通信的方式。
头发还在
2023/10/16
1470
Java多线程04——线程通信
【JUC】001-多线程回顾、synchronized与Lock锁
https://blog.csdn.net/qq_29689343/article/details/95861050
訾博ZiBo
2025/01/06
850
【JUC】001-多线程回顾、synchronized与Lock锁
Java线程(九):Condition-线程通信更高效的方式
该文介绍了Java线程的通信方式,包括同步、半同步、半异步、异步,以及各自的区别和适用场景。还介绍了Java中的线程池和线程池中的线程如何通信。最后,通过一个例子详细讲解了使用Java中的 Condition 实现线程通信。
高爽
2017/12/28
8910
多线程协作打印ABC之ReentrantLock版本
我们介绍了在Java里面使用synchronized + wait/notifyAll实现的多线程轮流打印特定的字符串,输出的结果如下:
我是攻城师
2018/12/26
1.2K0
聊一聊 ReentrantLock 类的一些玩法
在上一篇文章中,我们介绍了ReentrantLock类的一些基本用法,今天我们重点来介绍一下ReentrantLock其它的常用方法,以便对ReentrantLock类的使用有更深入的理解。
Java极客技术
2023/10/23
2090
聊一聊 ReentrantLock 类的一些玩法
深入理解Condition
建议先看一下这篇分享,深入理解AbstractQueuedSynchronizer,这篇文章主要介绍了AQS的同步队列实现,而本篇文章主要介绍AQS条件队列的实现
Java识堂
2019/08/13
4460
并发编程之ReentrantLock类使用介绍
在之前的线程系列文章中,我们介绍到了使用synchronized关键字可以实现线程同步安全的效果,以及采用wait()、notify()和notifyAll()方法,可以实现多个线程之间的通信协调,基本可以满足并发编程的需求。
Java极客技术
2023/10/23
2000
并发编程之ReentrantLock类使用介绍
相关推荐
Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验