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.同步 ...
随机推荐
- ubuntu下安装翻译软件
原文: http://sixipiaoyang.blog.163.com/blog/static/6232358820144146386437/ Ubuntu下常用的翻译软件有StarDict,Gol ...
- Kafka windows下的安装
1. 安装JDK 1.1 安装文件:http://www.oracle.com/technetwork/java/javase/downloads/index.html 下载JDK1.2 安装完成后需 ...
- MAPZONE GIS SDK接入Openlayers3之五——图形编辑工具
图形编辑工具提供对要素图形进行增.删.改的功能,具体包括以下几种工具类型: 浏览工具 选择工具 创建要素工具 删除命令 分割工具 合并命令 节点编辑工具 修边工具 撤销命令 重做命令 工具的实现基本上 ...
- 简单、强大的swig.js
Swig.js A simple, powerful, and extendable JavaScript Template Engine. 简单概括:JS模板引擎. Why to use 根据路劲渲 ...
- react 创建组件 (二)component
因为ES6对类和继承有语法级别的支持,所以用ES6创建组件的方式更加优雅,下面是示例: import React from 'react'; class Greeting extends React. ...
- 仿htc sense的弹性listView!
demo下载:http://pan.baidu.com/s/1ntoICdV 前一段时间换了htc m7之后,对htc的sense ui有不错的印象.特别是它的listview十分有个性.提供弹性的o ...
- 终端中的乐趣:6个有趣的Linux命令行工具
文章链接: http://hpw123.net/a/Linux/ruanjiananzhuang/2014/1103/117.html 很多其它文章尽在 http://www.hpw123.net ...
- SQL server 子查询的应用
设置主键关联表格 时间函数的应用
- BusHelper
https://github.com/eltld/-BusHelper https://github.com/eltld/BusLineSAX
- maven优化依赖
maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list能够列出项目最终解析到的依赖列表,dependency:tree能进一步的描绘项目依赖树,de ...