首页 > 其他分享 >AA BB CC AA线程打印 ,CC线程打印

AA BB CC AA线程打印 ,CC线程打印

时间:2024-08-31 15:54:06浏览次数:8  
标签:AA BB CC lock flag 线程 2023

Lock实现线程间定制化通信
合集 - JUC基础(13)
1.
JUC前置知识
2023-10-23
2.
Synchronized和Lock接口
2023-10-25
3.
线程间通信
2023-10-28
4.
Lock实现线程间定制化通信
2023-10-30
5.
常用集合线程安全分析
2023-11-02
6.
多线程锁
2023-11-12
7.
Callable接口和Future接口
2023-11-20
8.
JUC的强大辅助类
2023-11-22
9.
ReentrantReadWriteLock读写锁
2023-11-24
10.
BlockingQueue阻塞队列
2023-11-26
11.
线程池
2023-11-28
12.
Fork/Join
2023-12-01
13.
CompletableFuture异步回调
2023-12-01
收起
Lock实现线程间定制化通信
案例
要求
三个线程,AA BB CC AA线程打印5次,BB线程打印10次,CC线程打印15次

代码实现
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**

  • @author 长名06

  • @version 1.0

  • 线程定制化通信
    */
    //第一步,创建共享资源,和操作方法
    class ShareFlag {

    private Lock lock = new ReentrantLock();
    private int flag = 1;

    private Condition c1 = lock.newCondition();//一个Condition对象,只能唤醒由该对象阻塞的线程
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print5(int loop) throws InterruptedException {
    lock.lock();

     try {
         //第四步,避免虚假唤醒现象
         while (flag != 1) {//第2.1步 判断是否满足线程工作条件,阻塞
             c1.await();
         }
         //第2.2步 具体执行
         for (int i = 0; i < 5; i++) {
             System.out.println(Thread.currentThread().getName() + "\t" + i +"次输出"
                     + "flag=" + flag + "轮数" + loop);
         }
         flag = 2;
         //通知(唤醒等待线程)
         c2.signal();
     } finally {
         lock.unlock();
     }
    

    }

    public void print10(int loop) throws InterruptedException {
    lock.lock();

     try {
    
         while (flag != 2) {
             c2.await();
         }
    
         for (int i = 0; i < 10; i++) {
             System.out.println(Thread.currentThread().getName() + "\t" + i +"次输出"
                     + "flag=" + flag + "轮数" + loop);
         }
         flag = 3;
         //通知(唤醒等待线程)
         c3.signal();
     } finally {
         lock.unlock();
     }
    

    }

    public void print15(int loop) throws InterruptedException {
    lock.lock();

     try {
    
         while (flag != 3) {
             c3.await();
         }
    
         for (int i = 0; i < 15; i++) {
             System.out.println(Thread.currentThread().getName() + "\t" + i +"次输出"
                     + "flag=" + flag + "轮数" + loop);
         }
         flag = 1;
         //通知(唤醒等待线程)
    

//代码效果参考:https://www.weibow.com/sitemap/post.xml
c1.signal();
} finally {
lock.unlock();
}

}

}

public class ThreadDemoByCust {
public static void main(String[] args) {
ShareFlag shareFlag = new ShareFlag();

    new Thread(() -> {
        for (int i = 1; i <= 10; i++) {
            try {
                shareFlag.print5(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "AA").start();

    new Thread(() -> {
        for (int i = 1; i <= 10; i++) {
            try {
                shareFlag.print10(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "BB").start();

    new Thread(() -> {
        for (int i = 1; i <= 10; i++) {
            try {
                shareFlag.print15(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "CC").start();
}

}
学习时,关于代码的疑问
不理解,为什么一定是,AA线程执行完后,,BB线程执行完后,是c3是c2去执行唤醒一个等待线程操作去执行唤醒一个等待线程的操作,CC线程执行完后,是c1执行唤醒一个等待线程的操作。先往后面看,后续回来解答这个问题。

解答
是为了满足要求中的顺序,最开始三个AA,BB,CC线程,并行执行,因为flag初始值是1,所以AA先执行第一次循环,执行print5,然后循环输出5次后,flag = 2了(AA被c1阻塞),为了保证要求,再BB输出10次,则需要使用c2去唤醒BB线程,为什么是c2,因为BB线程在,最开始flag = 1时,是由c2去阻塞的,这里如果是c3对象阻塞的,则必须要用c3对象唤醒,因为Condition对象,只能唤醒由该对象阻塞的线程。后面BB线程切换CC线程,CC线程切换AA线程也是同理。

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

标签:AA,BB,CC,lock,flag,线程,2023
From: https://www.cnblogs.com/longshao2024/p/18390400

相关文章

  • python并发与并行(十) ———— 结合线程与协程,将代码顺利迁移到asyncio
    在前一篇中,我们用asyncio模块把通过线程来执行阻塞式I/O的TCP服务器迁移到了协程方案上面。当时我们一下子就完成了迁移,而没有分成多个步骤,这对于大型的项目来说,并不常见。如果项目比较大,那通常需要一点一点地迁移,也就是要边改边测,确保迁移过去的这一部分代码的效果跟原来相同。为......
  • python并发与并行(九) ———— 用asyncio改写通过线程实现的IO
    知道了协程的好处之后,我们可能就想把现有项目之中的代码全都改用协程来写,于是有人就担心,这样修改起来,工作量会不会比较大呢?所幸Python已经将异步执行功能很好地集成到语言里面了,所以我们很容易就能把采用线程实现的阻塞式I/O操作转化为采用协程实现的异步I/O操作。在这里我们要补充......
  • python并发与并行(四) ———— 用queue来协调多个线程之间的工作进度
    Python程序如果要同时执行多项任务,而这些任务又分别针对同一种产品的不同环节,那么就有可能得在它们之间进行协调。比较有用的一种协调方式是把函数拼接成管道。这样的管道与生产线比较像。它可以按先后顺序划分成几个阶段,每个阶段都由相应的函数负责。程序会把未经加工的原料放在生......
  • python并发与并行(三) ———— 利用Lock防止多个线程争用同一份数据
    了解到全局解释器锁(GIL)的效果之后,许多Python新手可能觉得没必要继续在代码里使用互斥锁(mutual-exclusionlock,mutex)了。既然GIL让Python线程没办法平行地运行在多个CPU核心上,那是不是就意味着它同时还会自动保护程序里面的数据结构,让我们不需要再加锁了?在列表与字典等结构上面测试......
  • JAVA多线程异步与线程池------JAVA
    初始化线程的四种方式继承Thread实现Runnable接口实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)线程池继承Thread和实现Runnable接口的方式,主进程无法获取线程的运算结果,不适合业务开发实现Callable接口+FutureTask可以获取线程内的返回结果,但是不利......
  • 一次惨痛的面试:“网易提前批,我被虚拟线程问倒了”
    一、写在开头昨晚收到一个粉丝在私信的留言如下:build哥,今天参加了网易的提前批,可以说是一次惨痛的面试体验......
  • CCF-CSP 2024 --重塑矩阵1,2c语言题解
     创作想法是因为像我当初大一时候想参加一些比赛但是奈何只学了c和c相关数据结构,但是对于许多竞赛的题目的题解往往都是c++或者其他面向对象的编程语言,让我们难以在c语言基础上入手这些比较复杂的题目。 创造的目的是为了帮助各位同时提高我对c语言编程的理解和锻炼个人......
  • saas收银系统源码(附部分代码)
    随着时代不断发展,很多连锁品牌不断涌现,门店数量也日益增多,但连锁品牌在选收银系统时,如果选择传统的SaaS模式合作,按门店数量、按功能模块收取服务费,门店数量如果多,每年也会是一笔不小的开支,其次连锁品牌的门店增多,门店的日常经营需求也会随之增多,比如需要对接第三方系统,添加一些自己......
  • 基于live555开发的多线程RTSPServer轻量级流媒体服务器EasyRTSPServer开源代码及其调
    EasyRTSPServer参考live555testProg中的testOnDemandRTSPServer示例程序,将一个live555testOnDemandRTSPServer封装在一个类中,例如,我们称为ClassEasyRTSPServer,在EasyRTSPServer_Create接口调用时,我们新建一个EasyRTSPServer对象,再通过调用EasyRTSPServer_Startup接口,将EasyRTSP......
  • IO进程练习:请在linux 利用c语言编程实现两个线程按照顺序依次输出”ABABABAB......“
    例如:a线程输出”A”之后b线程输出”B”,然后a线程输出“A”,再b线程输出”B”,之后往复循环。【1】使用信号量实现代码展示:#include<stdio.h>#include<pthread.h>#include<string.h>#include<semaphore.h>#include<unistd.h>//定义两个全局信号量,实现同步机制se......