Java 并发编程 (一)Semaphore和Exchanger的使用

news2024/9/24 7:18:48

Semaphore和Exchanger的使用

Semaphore

功能介绍

Semaphore 主要作用就是限制线程并发数量。
Semaphore 的构造函数中permits 可以控制最大并发数。每个线程可以acquire指定数量的 permit 。但是acquire n个 则需要释放n个。防止被阻塞

public class MySemaphore {
    // permits 控制最大许可数
    private Semaphore mySemaphore = new Semaphore(2);

    public void test(int permits){
        try {
            //获取锁 permits 表示该线程需要的许可数量 如果 当前许可数 > semaphore 的许可数量将会被阻塞
            mySemaphore.acquire(permits);
            System.out.println("acquire " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
            Thread.sleep(3000);
            System.out.println("release " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
            //释放锁 获取了n个许可 则需要释放n个许可
            mySemaphore.release(permits);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        MySemaphore mySemaphore = new MySemaphore();

        MyThread myThread1 = new MyThread(mySemaphore);
        MyThread myThread2 = new MyThread(mySemaphore);
        MyThread myThread3 = new MyThread(mySemaphore);
        myThread1.start();
        myThread2.start();
        myThread3.start();
    }

    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThread extends Thread{

        private MySemaphore mySemaphore;

        @Override
        public void  run(){
            mySemaphore.test(2);
        }
    }
}

在这里插入图片描述

使用acquireUninterruptibly() 可以防止 thread被 println

public class MySemaphore {
    // permits 控制最大许可数
    private Semaphore mySemaphore = new Semaphore(1);

    public void test(){
        try {
            //获取锁 permits 表示该线程需要的许可数量 如果 当前许可数 > semaphore 的许可数量将会被阻塞
            mySemaphore.acquireUninterruptibly();
            System.out.println("acquire " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
//            Thread.sleep(3000);
            for (int i = 0; i < Integer.MAX_VALUE/50; i++){
                String str = new String();
                Math.random();
            }
            System.out.println("release " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
            //释放锁 获取了n个许可 则需要释放n个许可
            mySemaphore.release();
        }catch (Exception e){
            System.out.println(Thread.currentThread().getName() + " interrupt");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MySemaphore mySemaphore = new MySemaphore();

        MyThread myThread1 = new MyThread(mySemaphore);
        MyThread myThread2 = new MyThread(mySemaphore);
        MyThread myThread3 = new MyThread(mySemaphore);
        myThread1.setName("myThread1");
        myThread1.start();
        myThread2.setName("myThread2");
        myThread2.start();
        myThread3.setName("myThread3");
        myThread3.start();
        Thread.sleep(1000);
        System.out.println("start interrupt a");
        myThread2.interrupt();
    }

    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThread extends Thread{

        private MySemaphore mySemaphore;

        @Override
        public void  run(){
            mySemaphore.test();
        }
    }
}

在这里插入图片描述

availablePermits() 获取当前可用的许可数
drainPermits() 立即返回可用的所有许可数,并且可讲许可数设置为0
hasQueuedThreads() 获取等待许可的线程数
hasQueuedThreads() 判断是都有线程在等待许可

在这里插入图片描述

可以 使用 tryAcquire 尝试获取许可 该方法可以保证线程不被阻塞。

应用场景

  • 多进路-多处理-多出路(多线程并发)
  • 多进路-单处理-多出路(多线程同时触发,串行运行)
  • pool池 (限制线程数量)
  • 多生产者/多消费者

Exchanger

功能介绍

Exchanger 可以使2个线程之间传输数据,比生产者/消费者更加方便。

public class MyExchanger {

    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThreadA extends Thread{

        private Exchanger<String> exchanger;

        @Override
        public void run(){
            try {
                System.out.println("A: " + exchanger.exchange("aaa"));
                System.out.println(Thread.currentThread().getName() + " end!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThreadB extends Thread{

        private Exchanger<String> exchanger;

        @Override
        public void run(){
            try {
                System.out.println("B: " + exchanger.exchange("bbb"));
                System.out.println(Thread.currentThread().getName() + " end!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        MyThreadA myThread = new MyThreadA(exchanger);
        myThread.start();
        MyThreadB myThreadB = new MyThreadB(exchanger);
        myThreadB.start();
        System.out.println("main end!");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/137620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python】鞭炮快乐响,春联贴门上,祝福送到你身旁

前言 大家早好、午好、晚好吖 ❤ ~ 现在贴春联已成风俗&#xff0c;红色的对联贴在大门上&#xff0c;房子顿时生辉。 正如诗云&#xff1a;“喜气临门红色妍&#xff0c;家家户户贴春联&#xff1b;旧年辞别迎新岁&#xff0c;时序车轮总向前。” 今天&#xff0c;我们就用p…

静态路由的拓展配置

静态路由的拓展配置&#xff1a; 1、负载均衡 当路由器访问同一个目标具有多条开销相似的路径&#xff08;经过路由器的数量&#xff09;时&#xff0c;可以让流量拆分后沿多条路径同时传输&#xff0c;可以达到叠加带宽的效果。&#xff08;当开销不相似时做负载均衡&#xff…

数据可视化系列-03AIPL消费者行为全链路可视化模型实践

文章目录4.AIPL消费者行为全链路可视化模型实践4.1、用户画像用户画像产生的原因用户画像概述用户画像构成原则第一类用户画像 User Persona第二类用户画像User Profile4.2、标签体系标签体系简介标签分类贴标签的方式标签的优化用户画像标签和权重4.3、用户画像大数据应用4.4、…

USB基础

一 USB 芯片组成 同以太网类似&#xff0c;USB芯片也分为Controller部分(主机控制器/设备控制器)和PHY部分(收发器) 两大部分组成。 Controller部分 主要实现USB的协议和控制&#xff0c;内部逻辑主要有 MAC层&#xff0c;CSR层&#xff0c;FIFO层等。 MAC层实现安装USB协议…

一文看懂 Redis 主从同步的原理

Redis 主从同步的基本原理有三种&#xff0c;分别是&#xff1a;全量复制&#xff0c;基于长链接的命令传播&#xff0c;增量复制。 接下来分别说说这三种主从间同步的原理。 全量复制 当我们启动多个 Redis 实例的时候&#xff0c;它们相互之间就可以通过 replicaof&#x…

新人转行IC该怎么选择岗位?(内附各岗位学习视频)

最近看到不少同学在后台提问&#xff1a;新人转行IC该怎么选择岗位&#xff1f;其实转行本身就是一件大事&#xff0c;转行之前一定要做好调研&#xff0c;选择适合自己的岗位&#xff0c;这样才能规划好职业生涯。 IC行业这几个岗位是最常见的&#xff1a;数IC前端设计工程师…

PoolFormer实战:使用PoolFormer实现图像分类任务(二)

文章目录训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整算法设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法运行以及结果查看测试热力图可视化展示完…

JSON数据解析

1.基础 JSON(JavaScript Object Notation) 是一种通用的轻量级数据交换文本格式。它很容易让人阅读和编写&#xff0c;也便于机器进行解析和生成。它使用JavaScript语法来存储和描述数据对象&#xff0c;但是JSON完全独立于JavaScript。JSON可适用于多种流行编程语言。这些特性…

JavaScript 用法

文章目录JavaScript 用法<script><script><script> 标签<body><body><body> 中的 JavaScriptJavaScript 函数和事件在 <head><head><head> 或者 <body><body><body> 的JavaScript<head><hea…

计算机网络知识解析

本篇文章主要讲的是计算机网络相关的内容&#xff0c;需要有一定的计算机网络的基础知识才能汲取更多的知识。当然没基础也可以看懂&#xff0c;会对计算机网络有一个基础的理解。在这一篇介绍中&#xff0c;我尽可能的覆盖一些面试中的问题&#xff0c;通过本篇文章&#xff0…

2022年吃瓜事件拆解,打造爆款,让你拥有顶级营销思维!

大环境下&#xff0c;谁又是幸存者&#xff1f;2022年吃瓜事件拆解&#xff0c;打造爆款&#xff0c;让你拥有顶级营销思维&#xff08;完整版&#xff09;&#xff01;小伍带你了解【商业营销内核】&#xff01;咱们开讲&#xff01;【事件1】张兰 vs 大S&#xff0c;大女主张…

【PyTorch学习1】B站刘二大人《PyTorch深度学习实践》——线性模型(Linear Model)

b站课程链接&#xff1a;线性模型 1.基本思想&#xff1a; 给出了一组一维数据&#xff0c;定义了一个简单的线性拟合函数&#xff0c;通过穷举法来列出一些权重&#xff08;拟合函数的系数&#xff09;&#xff0c;并计算这些权重对应的拟合损失函数&#xff08;使用均方误差…

C/C++智能指针详解

系列文章目录 文章目录系列文章目录前言一、什么是智能指针&#xff1f;二、使用方法1.shared_ptr2.unique_ptr3.weak_ptr前言 对C/C学习感兴趣的可以看看这篇文章哦&#xff1a;C/C教程 本章主要介绍一些C/C中智能指针的实现原理以及如何使用 一、什么是智能指针&#xff1…

计算机组成原理复习:存储器系统

计算机组成原理复习&#xff1a;存储器系统3.1 存储器的层次化结构3.2 半导体随机存储器&#xff08;RAM&#xff0c;易失性存储器&#xff09;3.2.1 静态随机存储器&#xff08;SRAM&#xff09;3.2.2 动态随机存储器&#xff08;DRAM&#xff09;3.2.3 只读存储器&#xff08…

token认证、Express中实现token的过程

一、token认证 1. 什么是token token的意思是“令牌"&#xff0c;是服务端生成的一串字符串&#xff0c;作为客户端进行请求的一个标识。当用户第一次登录后&#xff0c;服务器生成一个token并将此token返回给客户端&#xff0c;以后客户端只需带上这个token前来请求数据…

Jenkins搭建 笔记总结

文章目录1. 什么是CI/CD(DI)&#xff1f;2. 环境 安装部署3. 搭建 GitLab服务器&#xff08;ssh方式搭建&#xff09;4. 搭建 GitLab服务器&#xff08;Docker方式搭建&#xff09;4.1 搭建Docker环境4.2 docker容器 安装gitlab5. GitLab 提交代码6. Jenkins 配置Maven Git自动…

【信息论与编码 沈连丰】第五章:离散信道及其信道编码

【信息论与编码 沈连丰】第五章&#xff1a;离散信道及其信道编码第五章 离散信道及其信道编码5.1 信道的分类及其描述5.2 无扰离散信道的传输特性5.3 有扰离散信道的传输特性5.4 译码准则5.5 有扰离散信道的信道编码定理5.6 信道编码定理的应用第五章 离散信道及其信道编码 5…

6\8. 语义分析和中间代码生成

6&8. 语义分析和中间代码生成 从几个问题说起&#xff1a; 要计算 34*5 的值如何计算&#xff1f;按照以前的方法&#xff0c;我们会想到利用符号栈和数值栈来完成这个运算。但是有了语法分析之后我们不再需要进行这么复杂的代码构造了。第一&#xff0c;我们可以使用自顶…

AcWing1206.剪格子——学习笔记(未AC)

题目&#xff1a;1206. 剪格子 - AcWing题库https://www.acwing.com/problem/content/description/1208/ import java.util.Scanner;public class Main {public static void main(String args[]){//读数据Scanner input new Scanner(System.in);String MN input.nextLine();S…

Apache ShardingSphere分表的简单使用和常见问题

目录 简介 什么是 Apache ShardingSphere? 分库分表的背景 使用 pom 配置 1&#xff0c;application.properties配置文件 2&#xff0c;创建配置类 分表 验证分表 常见问题 自定义分表规则未生效 简介 官网&#xff1a;Apache ShardingSphere 版本&#xff1a;4…