java学习之浅谈多线程3--线程间协作

Java多线程--线程间的通信 阅读详情

通过保证临界区上多个线程的相互排斥,线程同步完全可以避免竞争状态的发生,但是有时还需要线程之间的协作。有两种方式可用于线程间的通信。
1.使用条件Condition
Condition接口:

+await():void           当前线程等待直到发生某个条件
+signal():void          唤醒一个等待线程
+signalAll():Condition  唤醒所有等待线程

条件是通过调用Lock对象的newCondition()方法而创建的对象,为了使用条件,必须首先获取锁,await()方法让线程等待并且自动释放条件上的锁,一旦条件正确,线程重新获取锁并且继续执行。创建了条件,该对象就可以使用await(),signal()和signalAll()方法。

考虑典型的消费者/生产者例子。假设使用缓冲区储存整数。缓冲区的大小是受限的。缓冲区提供write(int)方法将一个int值添加到缓冲区中,还提供方法read()从缓冲区中读取和删除一个int值为了同步这个操作,使用具有两个条件的锁:notEmpty(即缓冲区非空)和notFull(即缓冲区未满)。当任务向缓冲区添加一个int时,如果缓冲区是满的,那么任务将会等待notFull状态。当任务从缓冲区中删除一个int时,如果缓冲区是空的,那么任务将等待notEmpty状态。代码如下:

import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConsumerProducer {
    private static Buffer buffer = new Buffer();    //创建缓冲区

    public static void main(String[] args) {
        //创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);

        executor.execute(new ProducerTask());
        executor.execute(new ConsumerTask());

        executor.shutdown();
    }

    private static class ProducerTask implements Runnable {
        @Override
        public void run() {
            try {
                int i = 1;
                while(true) {
                    System.out.println("Producer writes " + i) ;
                    buffer.write(i++);
                    Thread.sleep((int)(Math.random() * 10000));
                }
            } catch (InterruptedException e) {
            }
        }
    }

    private static class ConsumerTask implements Runnable {
        @Override
        public void run() {
            try {
                while(true) {
                    System.out.println("\t\t\tConsumer reads " + buffer.read());
                    Thread.sleep((int)(Math.random() * 10000));
                }
            } catch (InterruptedException e) {

            }
        }
    }

    /**
     * 创建内部类Buffer作为缓冲区
     * @author zx
     *
     */
    private static class Buffer {
        private static final int CAPACITY = 1;  //缓冲区的大小
        private LinkedList<Integer> queue = new LinkedList<Integer>();  

        private static Lock lock = new ReentrantLock();     //创建一个锁

        //创建两个条件
        private static Condition notEmpty = lock.newCondition();    //缓冲区非空
        private static Condition notFull = lock.newCondition();     //缓冲区未满

        public void write(int value) {
            lock.lock();        //获得锁

            try {
                while(queue.size() == CAPACITY) {
                    System.out.println("Wait for notFull condition");
                    notFull.await();    //暂停当前线程,等待notFull条件
                }

                queue.offer(value);     //将整数value加入缓冲区
                notEmpty.signal();      //唤醒等待notEmpty条件的线程
            } catch (InterruptedException e) {
            } finally {
                lock.unlock();          //释放锁
            }
        }

        @SuppressWarnings("finally")
        public int read() {
            int value = 0;
            lock.lock();                //获得锁
            try {
                while(queue.isEmpty()) {
                    System.out.println("\t\tWait for notEmpty condition");
                    notEmpty.await();   //暂停线程等待notEmpty条件
                }

                value = queue.remove(); //从缓冲区删除一个整数
                notFull.signal();       //唤醒等待notFull条件的线程
            } catch (InterruptedException e) {
            } finally {
                lock.unlock();          //释放锁
                return value;
            }
        }

    }
}

2.使用阻塞队列

阻塞队列在试图向一个满队列添加元素或者从空队列中删除元素时会导致线程阻塞。BlockingQueue接口扩展java.util.Queue,并且提供同步的put和take方法向队列头添加元素,以及从队列尾删除元素。

Java支持三个具体的阻塞队列ArrayBlockingQueue、LinkedBlockingQueue和PriorityBlockingQueue。
ArrayBlockingQueue使用数组实现阻塞队列。必须指定一个容量或者可选的公平性来构造ArrayBlockingQueue。
LinkedBlockingQueue使用链表实现阻塞队列。可以创建不受限的或者受限的LinkedBlockingQueue。
PriorityBlockingQueue是优先队列,可以创建不受限的或者受限的优先队列。

下面的程序使用ArrayBlockingQueue来简化上面的生产者/消费者程序。创建一个ArrayBlockingQueue来存储整数,生产者线程将一个整数放入队列中,而消费者线程从队列中取走一个整数。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConsumerProducerUsingBlockingQueue {
    //创建buffer用来存储整数
    private static ArrayBlockingQueue<Integer> buffer = 
            new ArrayBlockingQueue<Integer>(2);

    public static void main(String[] args) {
        //创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);

        executor.execute(new ProducerTask());
        executor.execute(new ConsumerTask());

        executor.shutdown();
    }

    private static class ProducerTask implements Runnable {
        @Override
        public void run() {
            try {
                int i = 1;
                while(true) {
                    System.out.println("Producer writes " + i);
                    buffer.put(i++);        //向队列添加元素
                    Thread.sleep((int)(Math.random() * 10000));
                }
            } catch (InterruptedException e) {
            }
        }
    }

    private static class ConsumerTask implements Runnable {
        @Override
        public void run() {
            try {
                while(true) {
                    //从队列删除元素
                    System.out.println("\t\t\tConsumer reads " + buffer.take());
                    Thread.sleep((int)(Math.random() * 10000));
                }
            } catch (InterruptedException e) {
            }
        }
    }
}
单机多环境部署apollo 2.3.0 理解apollo的整体架构后,对比nacos配置中心功能点,其设计的复杂度以及完整度相较nacos而言更为丰富 对于不同的环境,例如 FAT, PRO 在部署时进程已经完全物理隔离,并且每个环境config/adminservice依赖的数据也完全物理隔离(连接不同的db),在数据隔离与安全方面做的很完善,但同时也提升了架构的复杂度 而 portal 可以管理多个环境,单节点部署虽然有单点问题,但并不会影响业务从configservice读取配置, 挂掉只要重启就可以,只是在 阅读详情

相关推荐

python 识别滑块验证码

博客来源于: https://www.cnblogs.com/wyh0923/p/16528354.html # -*- coding: utf-8 -*- # https://gov.pkulaw.cn/ 1. import io 2. import json 3. from pathlib import Path 4. from PIL import Image 5. import bas...

2102

java线程协作_Java并发之线程间的协作

上篇文章我们介绍了synchronized关键字,使用它可以有效的解决我们多线程所带来的一些常见问题。例如:竞态条件,内存可见性等。并且,我们也说明了该关键字主要是一个加锁和释放锁的集成,所有为能获得锁的线程都将被阻塞在某个对象的阻塞队列上。而我们本篇将要介绍的线程间的协作则主要是对对象的另一个队列的使用(条件队列),所有因条件不满足而无法继续运行的线程都将在条件队列上进行等待。主要涉及内容如下:...

weixin_39531229的博客 203

Sony微单相机alpha6000 wifi远程控制(1)

引言 Sony’s Camera Remote API beta SDK allows you to control a number of Sony cameras, including Sony Action cams, Sony Alpha cameras and Lens Style cameras, wirelessly from another device. 索尼于2017年三月Re...

markfuk996的博客 4966

java 多线程协作_Java多线程 3.线程协作

3.1 线程协作和线程安全关系线程协作指不同线程驱动的任务相互依赖,依赖一般就是对共享资源的依赖;有线程协作一定会有资源共享,有共享就有竞争,有竞争就会有线程安全问题;线程安全是通过synchronized和Lock机制来保证线程安全;线程协作通过Object的wait/notify方法,Thread的join/sleep/interrupt/yield,拥塞队列来实现;线程安全和线程协作编码时可...

weixin_33101399的博客 289

FPGA AXI DDR3读写时序调试与FIFO缓存实战解析

本文深入解析FPGA中AXI协议与DDR3的读写时序调试,重点探讨FIFO缓存在数据流控制中的关键作用。通过实战案例详细讲解突发传输中的地址对齐、数据分片等常见问题,并提供状态机设计、仿真波形分析和性能优化技巧,帮助开发者高效解决高速数据存储场景下的时序同步与数据一致性问题。

blockchain9miner的博客 1120

别再为采样窗口发愁了!手把手教你用STM32实现三电阻分扇区电流采样(附代码避坑)

本文详细介绍了STM32平台下三电阻分扇区电流采样的实现方法,重点解决采样窗口选择不当和扇区切换逻辑问题。通过PWM定时器与ADC协同工作的底层机制分析,提供可移植的代码示例和实战经验,帮助工程师在电机矢量控制(FOC)系统中实现高精度相电流采样。

weixin_42531516的博客 165

Java中的线程间协作

首先获取lockLock lock = new ReentrantLock();临界区:lock.lock();..............lock.unlock();协作:java.util.concurrent.Condition condition = lock.newCondition();condition.await();当前线程等待直到发生某个事件,(sign...

weixin_33804990的博客 110

iPhone用户必看:不装App也能搞定GitHub 2FA验证的3种方法(附恢复码管理技巧)

本文为iPhone用户提供了无需安装第三方App即可完成GitHub双重身份验证(2FA)的三种原生方案:利用相机扫码与iCloud钥匙串自动填充、使用iCloud钥匙串内置的TOTP验证码生成器,以及借助Safari浏览器扩展。文章详细解析了每种方法的操作步骤、适用场景,并重点强调了恢复码的安全管理与多层备份策略,帮助开发者在提升账户安全的同时,享受苹果生态的无缝便捷体验。

weixin_29324401的博客 655

Java并发之线程之间协作

线程之间的协作1.wait()和notify()、notifyAll()方法(这些方法均属于基类Object)wait()函数的调用使当前线程A被阻塞以等待某个外部条件的发生(这个外部条件超出了当前方法的控制能力),通常这个条件由另外一个任务B来改变,当另外的这个任务B调用notify()或则notifyAll()时,线程A将被唤醒。所以wait()提供了一种不同人物之间活动的一种同步方式。 调

惜暮 2146

国科大学习资料--高级软件工程-复习题选择题答案

国科大学习资料–高级软件工程(罗铁坚 魏峻 刘丹)-复习题选择题答案 ’‘

无名何许人的博客 1166

Unreal5 从入门到精通之 学习Niagara特效系统

UE5 Niagara粒子系统解析 Niagara是UE5中的高性能粒子特效系统,相比传统粒子系统具有完全可编程性和可视化节点编辑两大特点。核心单元发射器(Emitter)分为模板发射器(预设效果如喷泉、火焰)和空白发射器(高度自定义)。系统提供13种预设模板,包括吹飞粒子、五彩纸屑爆发、动态光束等常见特效。 Niagara采用三级模块化设计: 系统级:全局参数设置与更新 发射器级:控制粒子生成规则与行为 粒子级:处理单个粒子的生命周期和渲染 关键模块包括初始化粒子属性、物理模拟、颜色渐变等,支持GPU加速

TxNet 1124

Java多线程——线程间协作方式总结及使用示例

线程之间的协作方式方式一、wait()、notify()、notifyAll()wait()提供了一种在任务之间对活动同步的方式。wait()使你可以等待某个条件发生变化,通常,这种条件将由另一个任务来改变。 wait()会在等待外部世界发生变化的时候将任务挂起(而不是执行空循环,进行忙等待),并且只有在notify()或notifyAll()发生时,这个任务才会被唤醒并去检查所产生的变化。 调

zhoucheng05_13的博客 3900

网规第三版:第4章网络资源设备(完结)

第 4 章 网络资源设备 调整内容: 更新主流网络设备(交换机、路由器、防火墙)的技术参数与选型标准 增加国产化网络设备与信创产品的相关内容 精简已淘汰的设备类型与技术指标

鹿鸣天涯 268

java多线程学习三(线程间的共享和协作)

目录 ● yield()和join()方法简介 ● 线程间的共享 ● 线程间的协作 yield()和join()方法简介 yield()方法:使当前线程让出CPU占有权(线程让步),但让出的时间是不可设定的。也不会释放锁资源,所有执行yield()的线程有可能在进入到可执行状态后马上又被执行。...

小小时光 540

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java多线程初阶-线程协作与实战案例

本篇笔记深入探讨Java多线程进阶技术。首先讲解`wait`/`notify`机制,实现线程间的精准协作。接着,通过实战代码剖析了多种核心并发设计模式:确保对象唯一的单例模式、解耦利器生产者-消费者模型、资源复用的线程池(并优化了其关闭机制),以及任务调度的定时器。最后总结了保证线程安全的三大核心思路,帮助开发者构建健壮的并发应用。

weixin_73966418的博客 1591

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【Java多线程】你知道实现Java线程间通信有多少种方法吗?

文章目录1. 锁与同步2. 等待/通知机制3. 信号量4. 管道5. 其它通信相关5.1 join() 方法5.2 sleep() 方法sleep() 与 wait() 的区别5.3 ThreadLocal 类5.4 InheritableThreadLocal 合理地使用 Java 多线程可以更好地利用服务器资源。一般来讲,线程内部有自己私有的线程上下文,互不干扰。但是当我们需要多个线程之间相互协作的时候,就需要掌握 Java 线程的通信方式。下文将介绍 Java 线程之间的几种通信机制和原理。 1. 锁

aaa_hao的博客 4546

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

《五》多线程基础——Java线程间的通信(互斥与协作)

多线程基础——Java线程间的通信(互斥与协作)1、锁与同步   在Java中,锁的概念都是基于对象的,所以我们⼜经常称它为对象锁。线程同步听着很高大上,cao,被吓了一跳,其实就是让线程之间按照⼀定的顺序执⾏。怎么实现呢?我们可以使⽤锁来实现它。Java多线程的等待/通知机制是基于 Object 类的 wait() ⽅法和 notify() ,notifyAll() ⽅法来实现的。notify()⽅法会随机叫醒⼀个正在等待的线程,⽽notifyAll()会叫醒所有正在等待的线程。sleep() join(

xgb2018的博客 550

线程间协作

线程间协作 一、线程间协作:线程间的协作是为了解决线程执行时谁先谁后的为题,可以合理的确定多线程中线程的先后执行顺序 二、线程协作使用的方法:谁调用了wait方法,谁就必须调用notify或notifyAll方法,并且“谁”是对象锁 wait():对象锁调用了wait()方法,会使持有该对象锁的对象处于阻塞状态并释放对象锁的控制权,直到其他线程中的对象锁调用notify()方法或notif...

weixin_42867975的博客 510

Java 多线程解析:线程间的安全问题、线程间的通信问题与线程间的礼让问题

在 Java 编程领域,多线程是一个极为重要的概念,它能够显著提升程序的性能和响应能力,使程序能够更加高效地处理并发任务。本文将深入探讨 Java 中创建多线程的四种方式,以及多线程编程中的一些关键知识点,包括线程与进程的区别、线程安全问题、线程间通信、集合的线程安全性以及线程池的使用等。

天冬忘忧的博客 894

多线程(1):Java多线程基础以及线程间的协作

一.多线程基础概念 1.多线程的几种创建方式 (1)继承Thread类(也可用匿名内部类),重写run() 方法 (2)实现Runnable接口,重写run() 方法 (3)实现Callable接口 注意:实现Runnable和Callable接口的类只能当做一个 可以在线程中运行的任务,任务是通过线程驱动从而执行的,不是真正意义上的线程。最后还是通过Thread来调用,与Runna...

RuiKe的博客 346

Java核心复习 —— 线程间的协作

线程间的协作 线程之间如何进行协作,使得多个任务可以一起解决同一个问题。 这里出一个简单的题目。 要求使用A,B两个线程按顺序打印1-100,A打印奇数,B打印偶数。 这里就需要用到A和B两个线程来完成这个任务。解法会在本节最后列出。 wait()与notify() wait()方法的作用是,让线程一直处于等待中,在等待过程中,锁是释放的。如果在等待过程中,锁被别的线程获取了,咋整。 slee...

CoffeJoy 246

Java多线程——线程间消息队列的实现

JDK中有很多的阻塞的队列(Queue),这些队列可能是任务队列,可能是消息队列。 java线程间的消息队列:指的是消息在多线程之间的生产和消费的。 package com.leolee.multithreadProgramming.concurrent.messageQueue; import lombok.extern.slf4j.Slf4j; import java.util.LinkedList; /** * @ClassName Test * @Description: 消息队列模

保暖透气大裤衩LeoLee的博客 1890

JAVA学习心得—线程四:线程间的协作

线程间的协作: 首先看一个例程:要实现显示时间的功能,但是由于线程的抢占原因,所以不一定可以输出时间! package keeper; import java.util.Date; public class Test { private static String time; static class display extends Thread{ Time timeThread; ...

low1101的博客 149

Java多线程开发系列-线程间协作

wait(),notify()和notifyAll() 他们都是java.lang.Object的方法: wait(): Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. notify(...

昕友软件博客 205

实现Java多线程中的线程间通信

实现Java多线程中的线程间通信 大家好,我是微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 线程间通信的基本概念 在线程编程中,线程间通信是指多个线程之间通过共享内存或消息传递的方式进行交互和协作。Java提供了多种机制来实现线程间通信,如共享对象、wait/notify机制、管道、并发集合等。...

weixin_40742266的博客 110
上一篇: java学习之浅谈多线程2--线程同步
下一篇: java学习之浅谈多线程4--SwingWorker
zhangxinbetter
博客等级 码龄12年 5粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值