`
annan211
  • 浏览: 447225 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java多线程之Semaphore信号量详解

阅读更多
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ketqi.blog.51cto.com/1130608/1127274
   信号量在操作系统中一般用来管理数量有限的资源.每类资源有一个对应的信号量.信号量的值表示资源的可用数量.在使用资源时,要先从该信号量上获取一个使用许可.成功获取许可之后,资源可用数量减1.在持有许可期,使用者可以对获取资源进行操作.完成对资源的使用之后,需要在信号量上释放一个许可,资源可用数加1,允许其他使用者获取资源.当资源可用数为0的时候,需要获取资源的线程以阻塞的方式来等待资源变为可用,或者过段时间之后再检查资源是否变为可用.

   在java中有相应的Semaphore实现类,在创建Semaphore类的对象时指定资源的可用数,通过acquire方法以阻塞式的方式获取许可,而tryAcquire方法以非阻塞式的方式来获取许可.当需要释放许可时,使用release方法.Semaphore类也支持同时获取和释放多个资源的许可.通过acquire方法获取许可的过程是可以被中断的.如果不希望被中断,那么可以使用acquireUninterruptibly方法.Semaphore也支持在分配许可时使用公平模式,通过把构造方法的第二个参数设置为true来使用该模式.在公平模式下,当资源可用时,等待线程按照调用acquire方法申请资源的顺序依次获取许可.在进行资源管理时,一般使用公平模式,以避免造成线程饥渴问题.需要注意的是获取资源时,通过synchronized关键词或锁声明同步.这是因为Semaphore类只是一个资源数量的抽象表示,并不负责管理资源对象本身,可能有多个线程同时获取到资源使用许可,因此需要使用同步机制避免数据竞争.

package semaphore;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReentrantLock;

public class SemaphoreDemo2 {
    /** 可重入锁,对资源列表进行同步 */
    private final ReentrantLock lock = new ReentrantLock();
    /** 信号量 */
    private final Semaphore semaphore;
    /** 可使用的资源列表 */
    private final LinkedList<Object> resourceList = new LinkedList<Object>();

    public SemaphoreDemo2(Collection<Object> resourceList) {
        this.resourceList.addAll(resourceList);
        this.semaphore = new Semaphore(resourceList.size(), true);
    }

    /**
     * 获取资源
     *
     * @return 可用的资源
     * @throws InterruptedException
     */
    public Object acquire() throws InterruptedException {
        semaphore.acquire();

        lock.lock();
        try {
            return resourceList.pollFirst();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 释放或者归还资源
     *
     * @param resource 待释放或归还的资源
     */
    public void release(Object resource) {
        lock.lock();
        try {
            resourceList.addLast(resource);
        } finally {
            lock.unlock();
        }

        semaphore.release();
    }

    public static void main(String[] args) {
        //准备2个可用资源
        List<Object> resourceList = new ArrayList<Object>();
        resourceList.add("Resource1");
        resourceList.add("Resource2");

        //准备工作任务
        final SemaphoreDemo2 demo = new SemaphoreDemo2(resourceList);
        Runnable worker = new Runnable() {
            @Override
            public void run() {
                Object resource = null;
                try {
                    //获取资源
                    resource = demo.acquire();
                    System.out.println(Thread.currentThread().getName() + "\twork   on\t" + resource);
                    //用resource做工作
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "\tfinish on\t" + resource);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //归还资源
                    if (resource != null) {
                        demo.release(resource);
                    }
                }
            }
        };

        //启动9个任务
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 9; i++) {
            service.submit(worker);
        }
        service.shutdown();
    }
}

分享到:
评论

相关推荐

    JAVA 多线程之信号量(Semaphore)实例详解

    主要介绍了JAVA 多线程之信号量(Semaphore)实例详解的相关资料,需要的朋友可以参考下

    C#多线程之Semaphore用法详解

    //0表示创建Semaphore时,拥有可用信号量数值 //1表示Semaphore中,最多容纳信号量数值 Semaphore semaphore = new Semaphore(0, 1); Thread thread1 = new Thread(() =&gt; { //线程首先WaitOne等待一个可用的...

    详解java多线程的同步控制

    目录线程安全 Thread Safety重入锁 ReentrantLock读写锁 ReadWriteLock倒计数器 CountDownLatch循环栅栏 CyclicBarrier信号量 Semaphore 线程安全 Thread Safety JMM JMM(Java Memory Model)是一种基于计算机内存...

    个人总结的深入java多线程开发

    6)信号量Semaphore 31 7)ReentrantLock可重入的互斥锁定 Lock 32 8)阻塞队列BlockingQueue 34 9)已完成任务队列CompletionService 36 10)计时器CountDownLatch 37 11)周期性同步工具CyclicBarrier 38 12)异步计算的...

    NET多线程同步方法详解

    1) 互斥(Mutex), 信号量(Semaphore), 事件(AutoResetEvent/ManualResetEvent)2) 线程池 除了以上的这些对象之外实现线程同步的还可以使用Thread.Join方法。这种方法比较简单,当你在第一个线程运行时想等待第二个...

    java并发编程-AQS和JUC实战

    Semaphore信号量;ReadWriteLock读写锁;CountDownLatch计时器;CyclicBarrier循环栅栏; 重⼊锁可以完全替代synchronized关键字。在JDK5.0的早期版本中,重⼊锁的性能远远好于 synchronized,但从JDK6.0开始,JDK在...

    C#实现多线程的同步方法详解

    本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再...系统内核对象1)互斥(Mutex),信号量(Semaphore),事件(AutoResetEvent/ManualResetEvent)2)线程池除了以上的这些对象之外实现线程同步的还可

    详解Linux进程间通信——使用信号量

    而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。 信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待...

    c#线程同步使用详解示例

    在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。对于 Windows 应用程序,...线程同步有:临界区、互斥区、事件、信号量四种方式临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、

    详解python多线程之间的同步(一)

    这些技术包括临界区(Critical Section),互斥量(Mutex),信号量(Semaphore),事件Event等。 Event  threading库中的event对象通过使用内部一个flag标记,通过flag的True或者False的变化来进行操作。  名称  ...

    JAVA核心知识点整理(有效)

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

Global site tag (gtag.js) - Google Analytics