JAVA线程同步 (三)信号量
一个信号量有且仅有3种操作,且它们全部是原子的:初始化、增加和减少
增加可以为一个进程解除阻塞;
减少可以让一个进程进入阻塞。
信号量维护一个许可集,若有必要,会在获得许可之前阻塞每一个线程:
//从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
acquireUninterruptibly(int permits){}
每一个release()添加一个许可,从而可能释放一个正在阻塞的获取者。
Semaphore只对可用许可的号码进行计数,并采取相应的行动。
如何获得Semaphore对象?
public Semaphore(int permits,boolean fair)
permits:初始化可用的许可数目。
fair: 若该信号量保证在征用时按FIFO的顺序授予许可,则为true,否则为false;
如何从信号量获得许可?
public void acquire() throws InterruptedException
如何释放一个许可,并返回信号量?
public void release()
代码实例:
20个人去银行存款,但是该银行只有两个办公柜台,有空位则上去存钱,没有空位则只能去排队等待

package com.xhj.thread; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; /**
* 线程信号量Semaphore的运用
*
* @author XIEHEJUN
*
*/
public class SemaphoreThread {
private int a = 0; /**
* 银行存钱类
*/
class Bank {
private int account = 100; public int getAccount() {
return account;
} public void save(int money) {
account += money;
}
} /**
* 线程执行类,每次存10块钱
*/
class NewThread implements Runnable {
private Bank bank;
private Semaphore semaphore; public NewThread(Bank bank, Semaphore semaphore) {
this.bank = bank;
this.semaphore = semaphore;
} @Override
public void run() {
int b = a++;
if (semaphore.availablePermits() > 0) {
System.out.println("线程" + b + "启动,进入银行,有位置立即去存钱");
} else {
System.out.println("线程" + b + "启动,进入银行,无位置,去排队等待等待");
}
try {
semaphore.acquire();
bank.save(10);
System.out.println(b + "账户余额为:" + bank.getAccount());
Thread.sleep(1000);
System.out.println("线程" + b + "存钱完毕,离开银行");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} /**
* 建立线程,调用内部类,开始存钱
*/
public void useThread() {
Bank bank = new Bank();
// 定义10个新号量
Semaphore semaphore = new Semaphore(2);
// 建立一个缓存线程池
ExecutorService es = Executors.newCachedThreadPool();
// 建立20个线程
for (int i = 0; i < 10; i++) {
// 执行一个线程
es.submit(new Thread(new NewThread(bank, semaphore)));
}
// 关闭线程池
es.shutdown(); // 从信号量中获取两个许可,并且在获得许可之前,一直将线程阻塞
semaphore.acquireUninterruptibly(2);
System.out.println("到点了,工作人员要吃饭了");
// 释放两个许可,并将其返回给信号量
semaphore.release(2);
} public static void main(String[] args) {
SemaphoreThread test = new SemaphoreThread();
test.useThread();
}
}

线程0启动,进入银行,有位置立即去存钱
线程4启动,进入银行,有位置立即去存钱
线程1启动,进入银行,有位置立即去存钱
线程2启动,进入银行,有位置立即去存钱
线程3启动,进入银行,有位置立即去存钱
线程6启动,进入银行,无位置,去排队等待等待
0账户余额为:120
4账户余额为:120
线程5启动,进入银行,有位置立即去存钱
线程7启动,进入银行,无位置,去排队等待等待
线程8启动,进入银行,无位置,去排队等待等待
线程9启动,进入银行,无位置,去排队等待等待
线程4存钱完毕,离开银行
线程0存钱完毕,离开银行
1账户余额为:130
2账户余额为:140
线程1存钱完毕,离开银行
线程2存钱完毕,离开银行
3账户余额为:150
6账户余额为:160
线程6存钱完毕,离开银行
线程3存钱完毕,离开银行
5账户余额为:170
7账户余额为:180
线程5存钱完毕,离开银行
线程7存钱完毕,离开银行
8账户余额为:190
9账户余额为:200
线程9存钱完毕,离开银行
线程8存钱完毕,离开银行
到点了,工作人员要吃饭了
思考:
在很多情况下,可能有多个线程需要访问数目很少的资源。假想在服务器上运行着若干个回答客户端请求的线程。这些线程需要连接到同一数据库,但任一时刻
只能获得一定数目的数据库连接。你要怎样才能够有效地将这些固定数目的数据库连接分配给大量的线程?
答:1.给方法加同步锁,保证同一时刻只能有一个人去调用此方法,其他所有线程排队等待,但是此种情况下即使你的数据库链接有10个,也始终只有一个处于使用状态。这样将会大大的浪费系统资源,而且系统的运行效率非常的低下。
2.另外一种方法当然是使用信号量,通过信号量许可与数据库可用连接数相同的数目,将大大的提高效率和性能。
JAVA线程同步 (三)信号量的更多相关文章
- java 线程同步 原理 sleep和wait区别
java线程同步的原理java会为每个Object对象分配一个monitor, 当某个对象(实例)的同步方法(synchronized methods)被多个线程调用时,该对象的monitor将负责处 ...
- JAVA - 线程同步和线程调度的相关方法
JAVA - 线程同步和线程调度的相关方法 wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁:wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等 ...
- Java线程同步_1
Java线程同步_1 synchronized 该同步机制的的核心是同步监视器,任何对象都可以作为同步监视器,代码执行结束,或者程序调用了同步监视器的wait方法会导致释放同步监视器 synchron ...
- Java线程同步之一--AQS
Java线程同步之一--AQS 线程同步是指两个并发执行的线程在同一时间不同时执行某一部分的程序.同步问题在生活中也很常见,就比如在麦当劳点餐,假设只有一个服务员能够提供点餐服务.每个服务员在同一时刻 ...
- java线程 同步临界区:thinking in java4 21.3.5
java线程 同步临界区:thinking in java4 21.3.5 thinking in java 4免费下载:http://download.csdn.net/detail/liangru ...
- Java线程同步的四种方式详解(建议收藏)
Java线程同步属于Java多线程与并发编程的核心点,需要重点掌握,下面我就来详解Java线程同步的4种主要的实现方式@mikechen 目录 什么是线程同步 线程同步的几种方式 1.使用sync ...
- java 线程 (三)线程并发的安全性 同步代码块
package cn.sasa.demo1; import java.util.concurrent.ExecutionException; public class ThreadDemo { pub ...
- 【总结】Java线程同步机制深刻阐述
原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread ...
- Java线程同步和线程通信
一.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步. 不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全. 1.同步 ...
随机推荐
- Nginx的Web管理界面收集
Nginx实在是太强大了!灰度发布.金丝雀发布.负载均衡就只需要简单的几行配置就可以实现,这些特性嗾使微软无法比拟的. 原来Nginx除了使用ngx_http_stub_status_module模块 ...
- Oracle释放高水位线
/*****************************************************************原因:由于原导出数据库没有整理表空间其中主要包括两方面,一是用户产生 ...
- [Rust] Pass a JavaScript Function to WebAssembly and Invoke it from Rust
In some cases it’s useful to be able to invoke a JavaScript function inside Rust. This session showc ...
- Solidworks如何制作动画2
切换到Motion Study,然后定位到任意一帧,然后就可以摆弄当前装配体到新的位置和姿态,然后此时的时间和姿态就被记录下来了.以此类推可以多做几帧. 动画做好之后,点击播放可以预览.如果要保存,先 ...
- 用CSS美化你的HTML
CSS的简介: 1.CSS的定义:层叠样式表.属性和属性值用冒号分隔开,以分号结尾(这些符号都是英文的). 2.CSS得引入方式: 行内引入:<div style="这里写样式&quo ...
- C#中使用byte[]数据,生成Bitmap
/// <summary> /// 使用byte[]数据,生成256色灰度 BMP 位图 /// </summary> /// <param name="ori ...
- Java学习之基本概念
1.java体系结构: j2se:是Java的标准版,用于标准的应用开. j2ee:是Java的企业版,用于企业级的应用服务,web服务开发. j2me:是Java的微型版,用户手机或嵌入式开发. p ...
- Android中View的事件分发机制——Android开发艺术探索笔记
原文链接 http://sparkyuan.me/ 转载请注明出处 介绍 点击事件的事件分发就是对MotionEvent事件的分发过程.当一个MotionEvent产生了以后,系统须要把这个事件传递给 ...
- c++ string 之 find_first_not_of 源码
一:实现之前先说一所find_first_not_of姊妹函数() (1)find_first_of(string &str, size_type index = 0):(find_first ...
- 一个动态库连续注册的windows脚本regsvr32
cmd ->for %1 in (%windir%\system32\*.dll) do regsvr32.exe /s %1