线程间控制之Semaphore使用介绍

        Semaphore(信号量)通常用于限制访问某些(物理或逻辑)资源线程的数量。

        一个信号量维护一组许可证。每个acquire()都会阻塞,直到获得许可证;每个release()会释放许可证。如果没有线程需要获取许可证;信号量只是像其它池对象那样保持一个可用许可证的计数。

        池对象:线程池、数据库连接池等,创建一个池子,池子中已经建立好了连接,需要使用的时候直接从池子中拿来用。

一、Pool类源代码

        例子,这里有一个Pool类,它使用信号量来控制对项目池的访问

package ThreadStudy;

import java.util.concurrent.Semaphore;
//信号量通常用于限制访问某些(物理或逻辑)资源线程的数量
public class Pool {
	private final static int MAX_AVAILABLE = 100;
	//创建一个具有100许可证的信号量,采用公平方式获取许可证
	private final Semaphore semaphore = new Semaphore(MAX_AVAILABLE, true);

	public Object getItem() throws Exception {
		semaphore.acquire();
		return getNextAvailableItem();
	}

	public void putItem(Object x) {
		if (markAsUnused(x)) {
			semaphore.release();
		}
	}
	// 管理的任何类型的项目
	Object[] items = new Object[MAX_AVAILABLE];
	boolean[] used = new boolean[MAX_AVAILABLE];

	protected synchronized Object getNextAvailableItem() {
		for (int i = 0; i < MAX_AVAILABLE; i++) {
			if (!used[i]) {
				used[i] = true;
				return items[i];
			}
		}
		return null;
	}

	protected synchronized boolean markAsUnused(Object item) {
		for (int i = 0; i < MAX_AVAILABLE; ++i) {
			if (item == items[i]) {
				if (used[i]) {
					used[i] = false;
					return true;
				} else {
					return false;
				}

			}
		}
		return false;
	}
}

二、二进制信号量用法

        一个初始化为1的信号量,并且它最多只能有一个permit可用,可以作为互斥锁。这通常被称为二进制信号量,因为它只有两种状态:一个可用的许可证,或零可用的许可证。当以这种方式使用时,二进制信号量具有这样的属性(与许多锁实现不同),即“锁”可以由所有者以外的线程释放(因为信号量没有所有权的概念)。这在某些特定的上下文中可能很有用,比如死锁恢复。

package ThreadStudy;

import java.util.concurrent.Semaphore;

public class SemaphoreT2 {
	public static void main(String[] args) throws Exception {
		Semaphore semophore = new Semaphore(1);
		semophore.acquire();
		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					// 获取不到许可证,线程阻塞
					System.out.println(Thread.currentThread().getName()+"获取不到许可证,线程阻塞");
					semophore.acquire();
					System.out.println(Thread.currentThread().getName()+"获取到许可证,线程继续执行");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					// 释放许可证
					System.out.println(Thread.currentThread().getName()+"释放许可证");
					Thread.sleep(3000);
					semophore.release();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();

	}
}


三、Semaphore类中各种方法使用介绍

        1、俩个构造方法的区别,公平非公平!

Semaphore(int permits)创建一个具有给定许可数和不公平设置的信号量
Semaphore(int permits, boolean fair)创建一个具有给定许可数和给定公平性设置的信号量

        2、普通方法

获取许可证释放许可证

acquire()

从这个信号量获得一个许可,阻塞直到一个可用,或者线程被中断

release()

释放一个许可证,将其返回给信号量

acquire(int permits)

从信号量获取给定数量的许可

release(int permits)

释放给定的许可证数量,将它们返回给信号量

acquireUninterruptibly()

从信号量获得一个许可,阻塞直到一个可用

acquireUninterruptibly(int permits)

从信号量获取给定数量的许可

tryAcquire()

获取到许可证返回true,获取不到返回false

tryAcquire(int permits)
tryAcquire(int permits, long timeout, TimeUnit unit)
tryAcquire(long timeout, TimeUnit unit)

        3、代码示例

package ThreadStudy;

import java.util.concurrent.Semaphore;

public class SemaphoreT1 {
	public static void main(String[] args) {
		int MAX = 10;
		// 创建10个许可证
		Semaphore s = new Semaphore(MAX);
		for (int i = 0; i < MAX; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {

						System.out.println("等待获取许可证的线程数量评估值:" + s.getQueueLength());
						// 获取二个许可证
						s.acquire(2);
						
						System.out.println("返回此信号量中可用的当前许可数,此方法通常用于调试和测试目的:" + s.availablePermits());
						System.out.println("获取并返回所有立即可用的许可:" + s.drainPermits());
						// 和acquire的唯一区别就是,一直处于阻塞状态,除了获取到一个许可证
						s.acquireUninterruptibly();

						// 获取许可证,并且返回true,便于代码流程控制
						if (s.tryAcquire()) {
							System.out.println("tryAcquire返回为true");
						} else {
							System.out.println("tryAcquire返回为false");
						}
						Thread.sleep(1000);
						// 获取一个许可证
						s.acquire();
						// 获取5个许可证
						s.acquire(5);

						System.out.println("线程获取到许可:" + Thread.currentThread().getName());
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Semaphore(信号量)是Java中的一个同步控制工具类,它可以用来控制对共享资源的访问数量。在单线程并发的场景中,Semaphore通常用于控制资源的并发访问次数,以确保不会超出资源的处理能力。 在单线程并发的使用中,通常只有一个线程会访问受保护的资源,但可能会有多个并发的请求需要处理。通过 Semaphore,我们可以限制同时进行的处理数量,使得线程以一定的速率处理请求,而不是让线程在资源不可用时就直接阻塞,从而提高系统的吞吐量和资源的利用率。 以下是如何在单线程并发的场景中使用Semaphore的一个例子: 1. 创建一个Semaphore实例,并指定并发访问的最大数量。 2. 在请求处理逻辑中,调用`acquire()`方法获取信号量,如果信号量已经被其他请求占用,则当前线程将阻塞等待,直到有信号量可用。 3. 处理完请求后,调用`release()`方法释放信号量,使得其他线程可以继续获取信号量执行请求。 示例代码如下: ```java import java.util.concurrent.Semaphore; public class SingleThreadedConcurrency { private Semaphore semaphore; public SingleThreadedConcurrency(int permits) { semaphore = new Semaphore(permits); // 创建一个信号量,最大并发数为permits } public void processRequest() { try { semaphore.acquire(); // 尝试获取信号量,如果没有可用的信号量,则线程将阻塞 // 处理请求的代码逻辑... } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { semaphore.release(); // 释放信号量,允许其他线程进入 } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值