java多线程编程——同步器Semaphore(一)
网上关于解释Semaphore用法的代码很多,但是都不能运行或者运行错误。下面的例子是经过我自己运行过的。而且我详细的注释了下各个变量和方法的用途。希望对大家有用,一起研究。
import java.util.concurrent.Semaphore;/** * * @author Administrator * */public class PoolSemaphoreDemo {private static final int MAX_AVAILABLE = 5;private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);public static void main(String[] args) {final PoolSemaphoreDemo pool = new PoolSemaphoreDemo();Runnable runner = new Runnable() {public void run() {try {Object o;o = pool.getItem();Thread.sleep(1000);// 表示该线程睡眠1秒钟,即改线程不去竞争cpu处理时间1秒钟pool.putItem(o);} catch (InterruptedException e) {e.printStackTrace();}}};// 将上述线程重复执行10次for (int i = 0; i < 10; i++) {Thread t = new Thread(runner, "t" + i);t.start();}}/** * 从字符串池中取得最近一个可用的字符串资源,同时将标志位池中的状态设为true,表示有线程正在使用。 * * @return * @throws InterruptedException */public Object getItem() throws InterruptedException {System.out.println("线程:" + Thread.currentThread().getName()+ "开始从字符串资源池中取数据");available.acquire();return getNextAvailableItem();}/** * 将x对应的标志位池的状态修改为false,然后释放改字符串资源供其他线程读取 * * @param x */public void putItem(Object x) {if (markAsUnused(x)) {available.release();System.out.println("线程:" + Thread.currentThread().getName()+ "已经释放资源");}}// 需要循环取的字符串池protected Object[] items = { "AAA", "BBB", "CCC", "DDD", "EEE" };// 字符串池对应的标志位池,如果为true表示正在使用,其他线程不可用。如果为false,则表示其他线程可以用protected boolean[] used = new boolean[MAX_AVAILABLE];/** * 根据标志位数组得到items中有效的字符串 * * @return */protected synchronized Object getNextAvailableItem() {for (int i = 0; i < MAX_AVAILABLE; ++i) {if (!used[i]) {used[i] = true;System.out.println("线程:" + Thread.currentThread().getName()+ "从字符串池中取得资源:" + items[i]);return items[i];}}return null;}/** * 根据item将对应位置的标志位的值改为false * * @param item * @return */protected synchronized boolean markAsUnused(Object item) {for (int i = 0; i < MAX_AVAILABLE; ++i) {if (item == items[i]) {if (used[i]) {used[i] = false;System.out.println("线程:" + Thread.currentThread().getName()+ "开始向字符串池中放入资源:" + items[i]);return true;} elsereturn false;}}return false;}}