java多线程:11、信号量【Semaphore】

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *Semaphore  信号量
 */
public class ThreadTest2 {

    public static void main(String[] args) {

        ExecutorService threadPool=Executors.newCachedThreadPool();

        Semaphore sp = new Semaphore(3);

        for(int i=0;i<10;i++){
            threadPool.execute(new Runnable(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
//                      信号量获得许可
                        sp.acquire();
                        System.out.println(Thread.currentThread().getName()+"进入,当前"+(3-sp.availablePermits())+"个进程工作");
                        Thread.sleep(1000);

//                      释放一个许可
                        sp.release();
                        System.out.println(Thread.currentThread().getName()+"离开,当前"+(3-sp.availablePermits())+"个进程工作");

                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            });
        }

    }

}

以下为别人写的关于信号量的总结,感觉写的挺好因此引用借鉴
原文出处:http://www.cnblogs.com/XHJT/p/3910406.html

java笔记–对信号量Semaphore的理解与运用

在java中,提供了信号量Semaphore的支持。

Semaphore类是一个计数信号量,必须由获取它的线程释放,
通常用于限制可以访问某些资源(物理或逻辑的)线程数目。

一个信号量有且仅有3种操作,且它们全部是原子的:初始化、增加和减少
增加可以为一个进程解除阻塞;
减少可以让一个进程进入阻塞。

–如果朋友您想转载本文章请注明转载地址”http://www.cnblogs.com/XHJT/p/3910406.html “谢谢–

信号量维护一个许可集,若有必要,会在获得许可之前阻塞每一个线程:
//从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
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();
}

}
复制代码

面试题思考:
在很多情况下,可能有多个线程需要访问数目很少的资源。假想在服务器上运行着若干个回答客户端请求的线程。这些线程需要连接到同一数据库,但任一时刻
只能获得一定数目的数据库连接。你要怎样才能够有效地将这些固定数目的数据库连接分配给大量的线程?

答:1.给方法加同步锁,保证同一时刻只能有一个人去调用此方法,其他所有线程排队等待,但是此种情况下即使你的数据库链接有10个,也始终只有一个处于使

    用状态。这样将会大大的浪费系统资源,而且系统的运行效率非常的低下。


2.另外一种方法当然是使用信号量,通过信号量许可与数据库可用连接数相同的数目,将大大的提高效率和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值