首页 Java Java基础 Java并发编程,介绍常用的辅助类

Java并发编程,介绍常用的辅助类

Feb 02, 2021 pm 05:38 PM
java并发

Java并发编程,介绍常用的辅助类

相关免费学习推荐:java基础教程

常用的辅助类

  • 1.CountDownLatch
    • 1.2.示例:班长锁门问题
    • 1.2.CountDownLatch类简介:
      • 1.2.1 CountDownLatch概念
      • 1.2.3 CountDownLatch的用法
    • 1.3.CountDownLatch案例:
    • 1.4.原理总结
  • 2.CyclicBarrier
    • 2.1.CyclicBarrier简介
    • 2.2.案例:集齐7颗龙珠召唤神龙
  • 3.Semophore
    • 3.1.Semophore简介
    • 3.2.抢车位问题
    • 3.3.原理总结

1.CountDownLatch

1.2.示例:班长锁门问题

问题描述:假如有7个同学晚上上自习,钥匙在班长手上,并且要负责锁门。班长必须要等所有人都走光了,班长才能关灯锁门。这6个同学的顺序是无序的,不知道它们是何时离开。6个同学各上各的自习,中间没有交互。假如说6个学生是普通线程,班长是主线程,如何让主线程要等一堆线程运行完了,主线程才能运行完成呢。

public class CountDownLatchDemo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i=1;i<=6;i++){
			new Thread(()->{
				System.out.println(Thread.currentThread().getName()+"\t离开教室");
			},String.valueOf(i)).start();
		}
		System.out.println(Thread.currentThread().getName()+"\t班长关门走人");
	}}
登录后复制

运行结果截图
在这里插入图片描述
最后还有三个人被锁在教师了,这样可能会发生事故,所以肯定不行的。

我们要想实现这样的效果,就是等其它线程全部走完了,主线程才能运行。就需要借助JUC中的CountDownLatch类

1.2.CountDownLatch类简介:

1.2.1 CountDownLatch概念

CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。

CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务

CountDownLatch说明:count计数,down倒计算,Latch开始

1.2.3 CountDownLatch的用法

某一线程在开始运行前等待n个线程执行完毕。将CountDownLatch的计数器初始化为new CountDownLatch(n),每当一个任务线程执行完毕,就将计数器减1 countdownLatch.countDown(),当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。
CountDownLatch底层构造函数源代码

public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }
登录后复制

1.3.CountDownLatch案例:

public static void main(String[] args) throws InterruptedException {
		//6个同学正在上自习,每个人就有一个1计数器,走1个数字减1,main线程启动,必须要等计时器从6变成0,才能开始。
		CountDownLatch countDownLatch=new CountDownLatch(6);
		for(int i=1;i<=6;i++){
			new Thread(()->{
				System.out.println(Thread.currentThread().getName()+"\t离开教室");
				countDownLatch.countDown();		//计算减少一个
			},String.valueOf(i)).start();
		}
		countDownLatch.await();	//班长前面需要被阻塞
		System.out.println(Thread.currentThread().getName()+"\t班长关门走人");
	}
登录后复制

运行结果截图
在这里插入图片描述
这里每个人何时走并不知道, 但是可以保证每次都是班长最后一个走。

1.4.原理总结

CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会被阻塞。
其它线程调用countDown方法将会使计数器减1(调用countDown方法的线程不会阻塞)
当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。

2.CyclicBarrier

2.1.CyclicBarrier简介

cyclic循环,barrier屏障。
从字面上的意思可以知道,这个类的中文意思是“循环栅栏”。大概的意思就是一个可循环利用的屏障。
它的作用就是会让所有线程都等待完成后才会继续下一步行动。
上面班长关门的例子是做倒计时,这里是反过来,做加法,数到多少就开始。
比如人到齐了,再开会。,举个例子,就像生活中我们会约同事一起去开会,有些同事可能会早到,有些同事可能会晚到,但是这个会议规定必须等到所有人到齐之后才会让我们正式开会。这里的同事们就是各个线程,会议就是 CyclicBarrier。

构造方法

public CyclicBarrier(int parties)public CyclicBarrier(int parties, Runnable barrierAction)
登录后复制

解析:
parties 是参与线程的个数
第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务

我们通常用第二个构造函数。

2.2.案例:集齐7颗龙珠召唤神龙

public static void main(String[] args) {
		// TODO Auto-generated method stub
		CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{System.out.println("召唤神龙");});
		for(int i=1;i<=7;i++){
			final int tempInt=i;
			new Thread(()->{
				System.out.println(Thread.currentThread().getName()+"\t收集到第"+tempInt+"颗龙珠");
				try {
					//某个线程收集到了龙珠只能先等着,等龙珠收齐了才能召唤神龙
					cyclicBarrier.await();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			},String.valueOf(i)).start();;
		}
	}
登录后复制

截图
在这里插入图片描述

3.Semophore

3.1.Semophore简介

前面讨论的问题都是多对一的问题,我们现在可以讨论多对多的问题了。

假设有7个兄弟开车上班,而现在只有4个车位。7部车并列开进4个车位,每个车停了多长时间未知,资源被占用完了。假设有一个车只停了2s,那么它走了,外面的车又可以进来了。走一个进一个,最后全部都可以进去。而semophore就是控制多线程的并发策略。

简单理解来说,Semaphore:信号量主要用于两个目的:一个是用于多个共享资源的互斥使用;另一个用于并发线程数量的控制。

Semaphore类有两个重要方法

1、semaphore.acquire();
请求一个信号量,这时候信号量个数-1,当减少到0的时候,下一次acquire不会再执行,只有当执行一个release()的时候,信号量不为0的时候才可以继续执行acquire

2、semaphore.release();
释放一个信号量,这时候信号量个数+1,

3.2.抢车位问题

public static void main(String[] args) {
		//模拟6部车抢3个空车位
		Semaphore semaphore=new Semaphore(3);//模拟资源类,有3个空车位
		for(int i=1;i<=6;i++){
			new Thread(()->{
				try {
					//谁先抢到了,谁就占一个车位,并且要把semaphore中的资源数减1
					semaphore.acquire();
					System.out.println(Thread.currentThread().getName()+"\t抢占到了车位");
					TimeUnit.SECONDS.sleep(3);
					System.out.println(Thread.currentThread().getName()+"\t离开了车位");
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					//释放车位
					semaphore.release();
				}
				
			},String.valueOf(i)).start();
		}
	}
登录后复制

运行结果截图:
在这里插入图片描述

3.3.原理总结

在信号量上我们定义两种操作:

acquire(获取)当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等待下去,直到有线程释放信号量,或超时。

release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。

信号量主要用于两个目的:一个是用于多个共享资源的互斥使用;另一个用于并发线程数量的控制

如果把资源数从3变成1了,此时就等价于synchronized。

以上是Java并发编程,介绍常用的辅助类的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何在Java后端功能开发中处理并发访问? 如何在Java后端功能开发中处理并发访问? Aug 04, 2023 pm 08:22 PM

如何在Java后端功能开发中处理并发访问?在现代互联网应用中,高并发访问是一个常见的挑战。当多个用户同时访问后端服务时,如果不正确处理并发,可能会导致数据一致性、性能和安全性等问题。这篇文章将介绍一些在Java后端开发中处理并发访问的最佳实践。1.使用线程同步Java提供了多种机制来处理并发访问,其中最常用的是线程同步。通过在关键代码块或方法前添加synch

Java函数的并发和多线程中的Fork/Join框架如何使用? Java函数的并发和多线程中的Fork/Join框架如何使用? Apr 27, 2024 am 10:09 AM

如何在Java中使用Fork/Join框架创建并行任务?定义任务逻辑,计算结果或执行动作。创建ForkJoinPool管理并行线程。使用fork()方法提交任务。使用join()方法获取任务结果。

反射机制在Java并发中的应用? 反射机制在Java并发中的应用? Apr 15, 2024 pm 09:03 PM

答案:反射机制通过反射API允许Java程序在运行时检查和修改类和对象,在Java并发中可用于实现灵活的并发机制。应用:动态创建线程。动态改变线程优先级。注入依赖。

如何解决:Java并发错误:死锁检测 如何解决:Java并发错误:死锁检测 Aug 25, 2023 pm 10:03 PM

如何解决:Java并发错误:死锁检测在多线程编程中,死锁是一个常见的问题。当两个或多个线程互相等待对方释放锁资源时,就会发生死锁。死锁会导致线程被阻塞,资源无法释放,程序无法继续执行,从而导致系统出现故障。为了解决这个问题,Java提供了死锁检测机制。死锁检测是通过检查线程之间的依赖关系和资源申请排队情况来判断是否存在死锁的,一旦发现死锁,系统可以采取相应的

Java函数的并发和多线程中的阻塞队列作用是什么? Java函数的并发和多线程中的阻塞队列作用是什么? Apr 27, 2024 am 09:30 AM

阻塞队列:并发和多线程的强大工具阻塞队列是一种线程安全的队列,在并发和多线程编程中发挥着以下关键作用:线程同步:通过阻塞操作,防止争用条件和数据不一致。数据缓冲:作为数据缓冲区,缓解生产者和消费者线程速度不匹配的问题。负载平衡:控制队列中的元素数量,平衡生产者和消费者的负载。

解决Java并发竞态条件错误异常(ConcurrentRaceConditionErrorExceotion)的方法 解决Java并发竞态条件错误异常(ConcurrentRaceConditionErrorExceotion)的方法 Aug 26, 2023 pm 12:57 PM

解决Java并发竞态条件错误异常的方法竞态条件是指多个线程同时访问并修改共享资源时,最终结果的正确性受到执行顺序的影响。在Java中,当多个线程并发地访问共享资源时,如果没有正确地使用同步机制,就会出现竞态条件错误。当发生竞态条件错误时,程序可能会产生未预期的结果,甚至导致崩溃。本文将讨论如何解决Java并发竞态条件错误异常。一、使用同步机制最常见的解决竞态

如何解决:Java并发错误:线程死锁 如何解决:Java并发错误:线程死锁 Aug 18, 2023 pm 05:57 PM

如何解决:Java并发错误:线程死锁简介:在并发编程中,线程死锁是一个非常常见的问题。当多个线程在争夺资源时,若线程间发生相互等待对方释放资源的情况,就可能导致死锁。本文将介绍线程死锁的概念、产生原因,以及如何解决这个问题。线程死锁的概念当多个线程相互等待对方释放资源时,导致所有线程无法继续执行下去,形成了线程死锁。线程死锁的发生通常由于以下四个条件同时成立

在Java并发中,CountDownLatch和CyclicBarrier之间的区别是什么? 在Java并发中,CountDownLatch和CyclicBarrier之间的区别是什么? Sep 06, 2023 pm 03:33 PM

CountDownLatch和CyclicBarrier都用于多线程环境,并且它们都是多线程环境的一部分。根据JavaDoc-CountDownLatch-一种允许一个或多个线程等待的同步辅助工具直到其他线程中执行的一组操作完成。CyclicBarrier-一种同步辅助工具,允许一组线程相互等待到达公共屏障点。先生。编号KeyCyclicBarrierCountDownLatch1基本允许一组线程的同步辅助全部等待彼此到达公共障碍点。一种允许一个或多个线程的同步辅助工具等待其他线程中执行的一组操

See all articles