• Semaphore的介绍

    单词Semaphore的中文含义就是信号、信号系统的意思,此类的主要作用就是限制线程并发的数量。

    举个例子,一个屋子里有10个人,但只有一个窄门可以出去,这个窄门一次最多只能通过一人,这样就限制了同时出门的人数,同理也就是限制了线程并发的数量,这也就是Semaphore类要达到的目的。

  • 类Semaphore的同步性

    多线程中的同步就是多个线程排队去执行任务,一个一个执行,不会有线程安全的问题。

    构造函数参数permits是许可的意思,代表同一时间内,最多允许多少个线程同时执行acquire()和release()之间的代码。

    无参方法acquire()的作用是默认使用1个许可。

package com.wjg.unit1;

import java.util.concurrent.Semaphore;

public class Service {
private Semaphore semaphore = new Semaphore(1);
public void testMethod(){
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+" begin timer="+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName()+" end timer="+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
} }
} //运行类
package com.wjg.unit1; public class Run {
public static void main(String[] args) {
Service service = new Service();
Run run = new Run();
ThreadA a = run.new ThreadA(service);
a.setName("a");
a.start(); ThreadB b = run.new ThreadB(service);
b.setName("b");
b.start(); ThreadC c = run.new ThreadC(service);
c.setName("c");
c.start(); } public class ThreadA extends Thread { private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.testMethod();
}
} public class ThreadB extends Thread { private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.testMethod();
}
} public class ThreadC extends Thread { private Service service; public ThreadC(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.testMethod();
}
}
} 运行结果:
a begin timer=1487748505823
a end   timer=1487748510826
b begin timer=1487748510827
b end   timer=1487748515828
c begin timer=1487748515828
c end   timer=1487748520833
  • 构造函数permits参数作用

    参数permits代表同一时间内,最多允许有x个线程可以执行acquire()和release()之间的代码。我们将上例的Service改造一下,Run类不变

package com.wjg.unit1;

import java.util.concurrent.Semaphore;

public class Service {
//我们将premits参数值改为2
private Semaphore semaphore = new Semaphore(2);
public void testMethod(){
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+" begin timer="+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName()+" end timer="+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
} }
} 运行结果:
a begin timer=1487749198356
b begin timer=1487749198357
b end   timer=1487749203359
a end   timer=1487749203359
c begin timer=1487749203359
c end   timer=1487749208360
  • 方法acquire(int permits)使用

    方法acquire(int permits)功能就是每调用1次就使用x个许可。

    这个有一点说明一下,acquire方法做的是减法操作,release方法做的是加法操作,构造函数new Semaphore(5)中的5并不是最终的许可数量,仅仅是初始化的状态值,是可以动态改变的。

  • 方法acquireUninterruptibly()使用

    此方法作用是使等待进入acquire()方法的线程,不允许被中断。我们先看一下被中断的例子

    

package com.wjg.unit1;

import java.util.concurrent.Semaphore;

public class Service {
private Semaphore semaphore = new Semaphore(1); public void testMethod(){
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+" begin timer="+System.currentTimeMillis());
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String newString = new String();
Math.random();
}
System.out.println(Thread.currentThread().getName()+" end timer="+System.currentTimeMillis());
} catch (InterruptedException e) {
System.out.println("线程"+Thread.currentThread().getName()+"进入了catch");
e.printStackTrace();
}finally {
semaphore.release();
}
}
} package com.wjg.unit1; public class Run {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
Run run = new Run();
ThreadA a = run.new ThreadA(service);
a.setName("a");
a.start(); ThreadB b = run.new ThreadB(service);
b.setName("b");
b.start(); Thread.sleep(1000);
//中断b线程
b.interrupt();
System.out.println("main 中断了b");
} public class ThreadA extends Thread{
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.testMethod();
} } public class ThreadB extends Thread{
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.testMethod();
} }
} 执行结果:
a begin timer=1487751504264
main  中断了b
java.lang.InterruptedException
线程b进入了catch
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:996)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1303)
    at java.util.concurrent.Semaphore.acquire(Semaphore.java:317)
    at com.wjg.unit1_1_4.Service.testMethod(Service.java:10)
    at com.wjg.unit1_1_4.Run$ThreadB.run(Run.java:46)
a end   timer=1487751505711

    以上的例子就是把等待获取许可的线程B手动结束了,下面的例子是利用acquireUninterruptibly()方法阻止等待获取许可的线程中断。

package com.wjg.unit1_1_4;

import java.util.concurrent.Semaphore;

public class Service {
private Semaphore semaphore = new Semaphore(1); public void testMethod(){
try {
       //此处阻止等待获取许可的线程被中断
semaphore.acquireUninterruptibly();
System.out.println(Thread.currentThread().getName()+" begin timer="+System.currentTimeMillis());
for (int i = 0; i < Integer.MAX_VALUE/50; i++) {
String newString = new String();
Math.random();
}
System.out.println(Thread.currentThread().getName()+" end timer="+System.currentTimeMillis());
} finally {
semaphore.release();
}
}
} 执行结果
a begin timer=1487751777062
main  中断了b
a end   timer=1487751778455
b begin timer=1487751778455
b end   timer=148775177963
  • 方法availablePermits()和drainPermits()使用

    availablePermits()   返回Semaphore对象中当前可用的许可数

    drainPermits()      获取并返回立即可用的许可个数,并且将可用许可置0

  • 方法getQueueLength()和hasQueuedThreads()使用

    getQueueLength()   返回等待可续的线程个数

    hasQueuedThreads()   判断是否还有等待许可的线程

    这两个方法通常都是在判断当前有没有等待许可的线程信息时使用。

  • 公平与非公平信号量

    公平信号量是指获得锁的顺序与线程启动的顺序有关,非公平信息量就是无关的了。

    非公平信号量线程启动的顺序与调用semaphore.acquire()的顺序无关,也就是线程先启动了并不代表先获得许可。

    公平与不公平通过Semaphore类的构造函数new Semaphore(int permits,boolean fair)的第二个参数fair决定。

  • 方法tryAcquire()作用

    无参的tryAcquire()作用就是尝试地获得一个许可,如果获取不到则返回false,此方法通常与if语句结合使用,具有不阻塞的特点。

  • 方法tryAcquire(int permits)使用

     作用是尝试获取x个许可,如果湖区不到则返回false。

  • 方法tryAcquire(long timeout,TimeUnit unit)使用

     作用是在指定的时间内尝试地获取1个许可,如果获取不到则返回false,此处会有阻塞。

  • 方法tryAcquire(int permits,long timeout,TimeUnit unit)使用

    作用是在指定的时间内尝试地获取x个许可,如果获取不到则返回false,此处会有阻塞。    

注:本系列笔记均参考自《Java并发编程 核心方法与框架》此书。

多线程编程(一)-Semaphore(信号量)的使用的更多相关文章

  1. python网络编程--线程Semaphore(信号量)

    一:Semaphore(信号量) 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才 ...

  2. 多线程编程-- part 9 信号量:Semaphore

    Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可:当信号量 ...

  3. Java核心-多线程-并发控制器-Semaphore信号量

    Semaphore是非常有用的一个多线程并发控制组件(Java还有CountDownLatch.CyclicBarrier.Exchanger多线程组件),它相当于是一个并发控制器,是用于管理信号量的 ...

  4. C++多线程同步之Semaphore(信号量)

    一.线程间同步的几种方式 从上篇博文中可以发现,当多个线程对同一资源进行使用时,会产生“争夺”的情况,为了避免这种情况的产生,也就出现了线程间的同步这个技术.线程间的同步有多种方式,在接下来的博文中我 ...

  5. java 多线程 28 : 多线程组件之 Semaphore 信号量

    Semaphore是非常有用的一个组件,它相当于是一个并发控制器,是用于管理信号量的.构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问.我们需要控制并发的代码, ...

  6. Linux多线程编程-信号量

    在Linux中.信号量API有两组.一组是多进程编程中的System V IPC信号量.另外一组是我们要讨论的POSIX信号量. 这两组接口类似,但不保证互换.POSIX信号量函数都已sem_开头,并 ...

  7. Linux下多线程编程-信号量

    今天来谈谈线程的同步--信号量. 首先来看看一些概念性的东西: 如进程.线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行:B依言执行,再将结果给 ...

  8. 【C/C++多线程编程之七】pthread信号量

    多线程编程之信号量      Pthread是 POSIX threads 的简称.是POSIX的线程标准.          相互排斥量用来处理一个共享资源的同步訪问问题,当有多个共享资源时,就须要 ...

  9. 多线程锁:Mutex互斥体,Semaphore信号量,Monitor监视器,lock,原子操作InterLocked

    Mutex类 “mutex”是术语“互相排斥(mutually exclusive)”的简写形式,也就是互斥量.互斥量跟临界区中提到的Monitor很相似,只有拥有互斥对象的线程才具有访问资源的权限, ...

随机推荐

  1. 自我介绍和Github初次使用心得

    姓名:许洪科 班级:网络工程142 学号:1413042047 爱好:足球 编写过的程序:0 编写过的代码:几乎为0(大多数为网上直接复制的) Github注册过程:. 1:进入Github网站后点击 ...

  2. App与微信WebAPP

    我的App与微信搞上了 小麦积分墙摘自网络 最近有很多开发者关心的一个问题是如何提升app的下载量,透过现象开本质,app下载量的终极目标还是为多少客户提供了服务,抛开下载量KPI,app真心关心的问 ...

  3. 使用Team Explorer Everywhere (TEE) 2015 SDK获取团队项目的签入策略

    TFS的代码签入策略与IDE工具紧密相关,例如Visual Studio中设置的签入策略,只会影响Visual Studio的团队资源管理器:如果需要在Eclipse的TEE中启用签入策略,你还需要在 ...

  4. Jquery EasyUI 各组件属性、事件详解

    CSS类定义: div easyui-window                               window窗口样式 属性如下: 1)       modal:是否生成模态窗口.tru ...

  5. .Net Core IFormFile 始终为空的问题

    之前获取上传文件都是使用Request.Form.Files获取,直到这次改成定义形参 IFormFile时才遇到这个问题. // POST api/values [HttpPost] public ...

  6. Verify the Developer App certificate for your account is trusted on your device.

    1.报错内容 Could not launch "CH5203" Verify the Developer App certificate for your account is ...

  7. java public class和class的区别

  8. “全栈2019”22篇Java异常学习资料及总结

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"22篇Ja ...

  9. “全栈2019”Java异常第十二章:catch与异常匹配

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  10. HI~

    我是一只来自青岛某鶸校的蒟蒻,很高兴能认识各位,本人水平有限,文章中的不足之处,希望大家不吝赐教 我的邮箱是zhenshiluosuo@gmail.com 微信clearsummerday 联系时烦请 ...