前面我们介绍了2种同步机制:

1)使用synchronized关键字

2)使用Lock接口及其实现类:

ReentrantLock,ReentrantReadWriteLock.ReadLock, and ReentrantReadWriteLock.WriteLock

本例中,我们将学习更高级的同步方式:semaphore (信号量)

先看下概念:

Semaphores: A semaphore is a counter that controls the access to one ormore shared resources. This mechanism is one of the basic tools of concurrent programming and is provided by most of the programming languages.

一个信号量是控制读取一个或多个共享资源的计数器。

这一机制是并发编程中提供的一种基本工具并且绝大多数编程语言都有提供。

当一个线程想去读取某个共享资源,它必须获得信号。

如果semaphore大于0,这意味着当前资源处于空闲状态,这个时候它会减1,并允许该线程读取。



否则,信号将会让该线程睡眠直到信号量再次大于0。

当线程使用完共享资源后需要释放信号量,这样其它线程方能接着获取。

  1. PrintQueue.java
  1. package com.dylan.thread.ch3.c01.task;
  2. import java.util.concurrent.Semaphore;
  3. import java.util.concurrent.TimeUnit;
  4. /**
  5. * This class implements the PrintQueue using a Semaphore to control the
  6. * access to it.
  7. *
  8. */
  9. public class PrintQueue {
  10. /**
  11. * Semaphore to control the access to the queue
  12. */
  13. private final Semaphore semaphore;
  14. /**
  15. * Constructor of the class. Initializes the semaphore
  16. */
  17. public PrintQueue(){
  18. semaphore=new Semaphore(1);
  19. }
  20. /**
  21. * Method that simulates printing a document
  22. * @param document Document to print
  23. */
  24. public void printJob (Object document){
  25. try {
  26. // Get the access to the semaphore. If other job is printing, this
  27. // thread sleep until get the access to the semaphore
  28. semaphore.acquire();
  29. Long duration=(long)(Math.random()*10);
  30. System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),duration);
  31. Thread.sleep(duration);
  32. TimeUnit.SECONDS.sleep(duration);
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. } finally {
  36. // Free the semaphore. If there are other threads waiting for this semaphore,
  37. // the JVM selects one of this threads and give it the access.
  38. semaphore.release();
  39. }
  40. }
  41. }
  1. Job.java
  1. package com.dylan.thread.ch3.c01.task;
  2. /**
  3. * This class simulates a job that send a document to print.
  4. *
  5. */
  6. public class Job implements Runnable {
  7. /**
  8. * Queue to print the documents
  9. */
  10. private PrintQueue printQueue;
  11. /**
  12. * Constructor of the class. Initializes the queue
  13. * @param printQueue
  14. */
  15. public Job(PrintQueue printQueue){
  16. this.printQueue=printQueue;
  17. }
  18. /**
  19. * Core method of the Job. Sends the document to the print queue and waits
  20. * for its finalization
  21. */
  22. @Override
  23. public void run() {
  24. System.out.printf("%s: Going to print a job\n",Thread.currentThread().getName());
  25. printQueue.printJob(new Object());
  26. System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName());
  27. }
  28. }
  1. Main.java
  1. package com.dylan.thread.ch3.c01.core;
  2. import com.dylan.thread.ch3.Job;
  3. import com.dylan.thread.ch3.PrintQueue;
  4. /**
  5. * Main class of the example.
  6. *
  7. */
  8. public class Main {
  9. /**
  10. * Main method of the class. Run ten jobs in parallel that
  11. * send documents to the print queue at the same time.
  12. */
  13. public static void main (String args[]){
  14. // Creates the print queue
  15. PrintQueue printQueue=new PrintQueue();
  16. // Creates ten Threads
  17. Thread thread[]=new Thread[10];
  18. for (int i=0; i<10; i++){
  19. thread[i]=new Thread(new Job(printQueue),"Thread "+i);
  20. }
  21. // Starts the Threads
  22. for (int i=0; i<10; i++){
  23. thread[i].start();
  24. }
  25. }
  26. }

运行结果:

Thread 3: Going to print a job
Thread 9: Going to print a job
Thread 5: Going to print a job
Thread 7: Going to print a job
Thread 4: Going to print a job
Thread 0: Going to print a job
Thread 2: Going to print a job
Thread 1: Going to print a job
Thread 8: Going to print a job
Thread 6: Going to print a job
Thread 3: PrintQueue: Printing a Job during 2 seconds
Thread 9: PrintQueue: Printing a Job during 5 seconds
Thread 3: The document has been printed
Thread 9: The document has been printed
Thread 5: PrintQueue: Printing a Job during 9 seconds
Thread 5: The document has been printed
Thread 7: PrintQueue: Printing a Job during 7 seconds
Thread 7: The document has been printed
Thread 4: PrintQueue: Printing a Job during 9 seconds
Thread 0: PrintQueue: Printing a Job during 6 seconds
Thread 4: The document has been printed
Thread 0: The document has been printed
Thread 2: PrintQueue: Printing a Job during 5 seconds
Thread 2: The document has been printed
Thread 1: PrintQueue: Printing a Job during 1 seconds
Thread 8: PrintQueue: Printing a Job during 5 seconds
Thread 1: The document has been printed
Thread 8: The document has been printed
Thread 6: PrintQueue: Printing a Job during 3 seconds
Thread 6: The document has been printed

Java并发编程实例--20.使用Semaphores(信号量)控制资源的并发读取的更多相关文章

  1. 【Java并发编程】6、volatile关键字解析&内存模型&并发编程中三概念

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...

  2. Python并发编程实例教程

    有关Python中的并发编程实例,主要是对Threading模块的应用,文中自定义了一个Threading类库. 一.简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态 ...

  3. Java并发编程系列-(9) JDK 8/9/10中的并发

    9.1 CompletableFuture CompletableFuture是JDK 8中引入的工具类,实现了Future接口,对以往的FutureTask的功能进行了增强. 手动设置完成状态 Co ...

  4. java多线程编程实例

    [转]这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下. 1.三个售票窗口同时出售20张票程序分析:   ...

  5. C#并发编程实例讲解-概述(01)

    在工作中经常遇到需要并发编程的实例,一直没有时间来整理,现在空了下来,个人整理对并发一下理解. 关于并发编程的几个误解 误解一:并发编程就是多线程 实际上多线只是并发编程的一中形式,在C#中还有很多更 ...

  6. Java并发编程实例(synchronized)

    此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...

  7. Java并发编程原理与实战三十三:同步容器与并发容器

    1.什么叫容器? ----->数组,对象,集合等等都是容器.   2.什么叫同步容器? ----->Vector,ArrayList,HashMap等等.   3.在多线程环境下,为什么不 ...

  8. ~~并发编程(十三):信号量,Event,定时器~~

    进击のpython ***** 并发编程--信号量,Event,定时器 本节需要了解的就是: 信号量,以及信号量和互斥锁的区别 了解时间和定时器,以及使用 信号量 信号量也是锁,本质没有变!但是他跟互 ...

  9. 《Java并发编程的艺术》读书笔记:一、并发编程的目的与挑战

    发现自己有很多读书笔记了,但是一直都是自己闷头背,没有输出,突然想起还有博客圆这么个好平台给我留着位置,可不能荒废了. 此文读的书是<Jvava并发编程的艺术>,方腾飞等著,非常经典的一本 ...

  10. [笔记][Java7并发编程实战手冊]3.4 等待多个并发事件的完毕CountDownLatch倒计数闭锁

    [笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 本文学习CountDownLatch 倒计数闭锁. 本人英文不好.靠机器翻译,然后有一段非常形象的描写叙述,让我把它叫为倒计数 用给定的计数 ...

随机推荐

  1. Redis和Springboot在Windows上面设置开机启动的方法

    Redis和Springboot在Windows上面设置开机启动的方法 背景 同事遇到一个问题 Windows 晚上自动更新服务 然后第二天 Springboot开发的程序没有启动起来. 所以基于此想 ...

  2. Oracle session的sid与serial的简单学习

    Oracle session的sid与serial的简单学习 ITPUB vage的说法 这样说吧,Oracle允许的会话数(或者说连接数)是固定的,比如是3000个.假设每个会话要占1K字节,哪一共 ...

  3. [转帖]TiDB修改配置参数

    https://www.jianshu.com/p/2ecdb4642579 在TiDB 中,"修改配置参数"似乎是个不精准的说法,它实际包含了以下内容: 修改 TiDB 的系统变 ...

  4. [转帖]Linux字符截取命令-cut

    概述 cut是一个选取命令,.一般来说,选取信息通常是针对"行"来进行分析的,并不是整篇信息分析的. 语法 cut [-bn] [file] 1 或 cut [-c] [file] ...

  5. [转帖]MioIO读/写性能测试

    https://www.jianshu.com/p/a0a84f91b16f   image.png COSBench是Intel团队基于java开发,是一个测试云对象存储系统的分布式基准测试工具,全 ...

  6. [转帖]华为FusionSphere虚拟化解决方案介绍

    https://huaweicloud.csdn.net/63566589d3efff3090b5d243.html?spm=1001.2101.3001.6650.2&utm_medium= ...

  7. 【转】Java类加载器:类加载原理解析

    [转]Java类加载器:类加载原理解析 https://www.jianshu.com/p/1f704ad4196e 摘要: 每个开发人员对java.lang.ClassNotFoundExcetpi ...

  8. 【k哥爬虫普法】非法入侵计算机信息系统,获取1500万余条个人信息!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...

  9. 深入浅出Java多线程(一):进程与线程

    引言 大家好,我是你们的老伙计秀才. 在计算机系统的发展历程中,早期的计算机操作模式十分单一和低效.用户只能逐条输入指令,而计算机则按照接收指令的顺序逐一执行,一旦用户停止输入或进行思考,计算机会处于 ...

  10. conda创建虚拟环境后文件夹中只有conda-meta文件夹,无法将环境添加到IDE中

    1.问题描述:anaconda的envs的其中一个环境目录下,没有python.exe文件,只有conda-meta和scripts 平时创建虚拟环境都是: conda create -n test ...