读书人

java多线程编程同步器Se地图hore(

发布时间: 2012-12-23 11:28:15 作者: rapoo

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;}}


Semaphore的用途中需要注意的就是,当release()或者acquire()时,如果当前线程不能获取到资源,那么当前线程会阻塞。知道获取到资源为止,这点可以从输出结果中可以看到。

下面是运行结果

线程:t0开始从字符串资源池中取数据
线程:t0从字符串池中取得资源:AAA
线程:t1开始从字符串资源池中取数据
线程:t1从字符串池中取得资源:BBB
线程:t3开始从字符串资源池中取数据
线程:t3从字符串池中取得资源:CCC
线程:t5开始从字符串资源池中取数据
线程:t5从字符串池中取得资源:DDD
线程:t7开始从字符串资源池中取数据
线程:t7从字符串池中取得资源:EEE
线程:t9开始从字符串资源池中取数据
线程:t2开始从字符串资源池中取数据
线程:t4开始从字符串资源池中取数据
线程:t6开始从字符串资源池中取数据
线程:t8开始从字符串资源池中取数据
线程:t0开始向字符串池中放入资源:AAA
线程:t0已经释放资源
线程:t9从字符串池中取得资源:AAA
线程:t1开始向字符串池中放入资源:BBB
线程:t1已经释放资源
线程:t3开始向字符串池中放入资源:CCC
线程:t3已经释放资源
线程:t2从字符串池中取得资源:BBB
线程:t4从字符串池中取得资源:CCC
线程:t5开始向字符串池中放入资源:DDD
线程:t5已经释放资源
线程:t7开始向字符串池中放入资源:EEE
线程:t7已经释放资源
线程:t6从字符串池中取得资源:DDD
线程:t8从字符串池中取得资源:EEE
线程:t9开始向字符串池中放入资源:AAA
线程:t9已经释放资源
线程:t4开始向字符串池中放入资源:CCC
线程:t4已经释放资源
线程:t2开始向字符串池中放入资源:BBB
线程:t2已经释放资源
线程:t8开始向字符串池中放入资源:EEE
线程:t8已经释放资源
线程:t6开始向字符串池中放入资源:DDD
线程:t6已经释放资源

读书人网 >编程

热点推荐