多线程-利用semaphore多线程顺序打印ABC

semaphore介绍

先说它的构造方法:

    //参数permits是许可的数量
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }

    //第二个参数是,是否是公平锁
    /**
     * Creates a {@code Semaphore} with the given number of
     * permits and the given fairness setting.
     *
     * @param permits the initial number of permits available.
     *        This value may be negative, in which case releases
     *        must occur before any acquires will be granted.
     * @param fair {@code true} if this semaphore will guarantee
    //fair为true的时候,semaphore保证在竞争permits的时候先进先出,先获得许可先执行
     *        first-in first-out granting of permits under contention,
     *        else {@code false}
     */
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }
公平信号量是指获得锁的顺序与线程启动的顺序有关,非公平信息量就是无关的了。
非公平信号量线程启动的顺序与调用semaphore.acquire()的顺序无关,也就是线程先启动了并不代表先获得许可。

公平与不公平通过Semaphore类的构造函数new Semaphore(int permits,boolean fair)的第二个参数fair决定。

再说说它的两个方法:

    /**
    //官方文档解释的很清楚,从semaphore(信号量)对象中获取一个许可,此semaphore许可permits数量会减1,如果当前许可的数量为0,
//线程会阻塞直到有可用的许可permit 或者线程被中断
     * Acquires a permit from this semaphore, blocking until one is
     * available, or the thread is {@linkplain Thread#interrupt interrupted}.
     *
     * <p>Acquires a permit, if one is available and returns immediately,
     * reducing the number of available permits by one.
     *
     * <p>If no permit is available then the current thread becomes
     * disabled for thread scheduling purposes and lies dormant until
     * one of two things happens:
     * <ul>
    //此semaphore对象permits数量增加,需要其他线程调用此semaphore对象的release方法
     * <li>Some other thread invokes the {@link #release} method for this
     * semaphore and the current thread is next to be assigned a permit; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * the current thread.
     * </ul>
     *
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
     * for a permit,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     *
     * @throws InterruptedException if the current thread is interrupted
     */
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    /**
     * Releases a permit, returning it to the semaphore.
     *
    //释放一个许可,是permits的数量加1,
     * <p>Releases a permit, increasing the number of available permits by
     * one.  If any threads are trying to acquire a permit, then one is
     * selected and given the permit that was just released.  That thread
     * is (re)enabled for thread scheduling purposes.
     *
     * <p>There is no requirement that a thread that releases a permit must
     * have acquired that permit by calling {@link #acquire}.
     * Correct usage of a semaphore is established by programming convention
     * in the application.
     */
    public void release() {
        sync.releaseShared(1);
    }

顺序打印ABC思路

定义三个线程“ThreadA”、“ThreadB”、“ThreadC”它们的run()方法分别打印"A",“B”,“C”,我们定义三个信号量对象来控制线程ABC的执行顺序,初始化A信号量semaphore的permits的数量为1,线程ThreadA 执行run前调用信号量A对象的acquire()方法,所以A线程可以执行。初始化B、C信号量的permits数量为0,在线程ThreadB、ThreadC执行前分别调用B、C信号量的acquire()方法,由于permits的数量为0,所有ThreadB、ThreadC线程会阻塞。打印完“A”字母之后,我们调用B信号量的release()方法,这样阻塞的ThreadB线程就能顺利执行了,以此类推完成“A”,“B”,“C”的顺序打印。

import java.util.concurrent.Semaphore;

public class ABC_Semaphore {
    // 以A开始的信号量,初始信号量数量为1
    private static Semaphore A = new Semaphore(1,true);
    // B、C信号量,A完成后开始,初始信号数量为0
    private static Semaphore B = new Semaphore(0);
    private static Semaphore C = new Semaphore(0);

    static class ThreadA extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    A.acquire();// A获取信号执行
                    System.out.println("A");
                    B.release();// B释放信号,B信号量为1,可以执行
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class ThreadB extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    B.acquire();
                    System.out.println("B");
                    C.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class ThreadC extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    C.acquire();
                    System.out.println("C");
                    System.out.println("---------------------");
                    A.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //顺序打印abc
        new ThreadA().start();
        new ThreadB().start();
        new ThreadC().start();
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值