0
点赞
收藏
分享

微信扫一扫

三、多线程

kiliwalk 2022-02-26 阅读 33

Semaphore
Semaphore是一个计数信号量。
从概念上将,Semaphore包含一组许可证。
如果有需要的话,每个acquire()方法都会阻塞,直到获取一个可用的许可证。
每个release()方法都会释放持有许可证的线程,并且归还Semaphore一个可用的许可证。
然而,实际上并没有真实的许可证对象供线程使用,Semaphore只是对可用的数量进行管理维护
总结:如果线程要访问一个资源就必须先获得信号量。如果信号量内部计数器大于0,信号量减1,然后允许共享这个资源;否则,如果信号量的计数器等于0,信号量将会把线程置入休眠直至计数器大于0.当信号量使用完时,必须释放

1114. 按序打印(简单)

class Foo {

    Semaphore s12 = new Semaphore(0);
    Semaphore s23 = new Semaphore(0);

    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        s12.release();//释放后s12的值会变成1
    }

    public void second(Runnable printSecond) throws InterruptedException {
        s12.acquire();//没有会阻塞  当为1的时候,说明线程2可以拿到s12了
        printSecond.run();
        s23.release();//释放后s23的值会变成1
    }

    public void third(Runnable printThird) throws InterruptedException {
        s23.acquire();//0的时候拿不到,1的时候可以拿到
        printThird.run();
    }
}

1115. 交替打印 FooBar(中等)

在这里插入图片描述

class FooBar {
            private int n;

            private Semaphore fooSema = new Semaphore(1);
            private Semaphore barSema = new Semaphore(0);

            public FooBar(int n) {
                this.n = n;
            }

            public void foo(Runnable printFoo) throws InterruptedException {

                for (int i = 0; i < n; i++) {
                    fooSema.acquire();//值为1的时候,能拿到,执行下面的操作
                    printFoo.run();
                    barSema.release();//释放许可给barSema这个信号量 barSema 的值+1
                }
            }

            public void bar(Runnable printBar) throws InterruptedException {

                for (int i = 0; i < n; i++) {
                    barSema.acquire();//值为1的时候,能拿到,执行下面的操作
                    printBar.run();
                    fooSema.release();//释放许可给fooSema这个信号量 fooSema 的值+1
                }
            }
        }


1116. 打印零与奇偶数(中等)

class ZeroEvenOdd {
    private int n;
    private Semaphore zeroSema = new Semaphore(1);
    private Semaphore oddSema = new Semaphore(0);//奇数
    private Semaphore evenSema = new Semaphore(0);//偶数

    public ZeroEvenOdd(int n) {
        this.n = n;
    }

    public void zero(IntConsumer printNumber) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            zeroSema.acquire();
            printNumber.accept(0);
            if ((i & 1) == 1) {//奇数
                oddSema.release();
            } else {
                evenSema.release();
            }
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            if ((i & 1) == 0) {//偶数 打印偶数 并释放zero的线程
                evenSema.acquire();
                printNumber.accept(i);
                zeroSema.release();
            }
        }
    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            if ((i & 1) == 1) {//奇数,打印奇数,并释放zero的线程
                oddSema.acquire();
                printNumber.accept(i);
                zeroSema.release();
            }
        }
    }
}


1195. 交替打印字符串(中等)


class FizzBuzz {
    private int n;
    private Semaphore f;
    private Semaphore b;
    private Semaphore fB;
    private Semaphore num;

    public FizzBuzz(int n) {
        this.n = n;
        num = new Semaphore(1);
        f = new Semaphore(0);
        b = new Semaphore(0);
        fB = new Semaphore(0);
    }

    // printFizz.run() outputs "fizz".
    public void fizz(Runnable printFizz) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            if (i % 3 == 0 && i % 5 != 0) {
                f.acquire();
                printFizz.run();
                num.release();
            }
        }
    }

    // printBuzz.run() outputs "buzz".
    public void buzz(Runnable printBuzz) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            if (i % 5 == 0 && i % 3 != 0) {
                b.acquire();
                printBuzz.run();
                num.release();
            }
        }
    }

    // printFizzBuzz.run() outputs "fizzbuzz".
    public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            if (i % 5 == 0 && i % 3 == 0) {
                fB.acquire();
                printFizzBuzz.run();
                num.release();
            }
        }
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void number(IntConsumer printNumber) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            num.acquire();
            if (i % 3 != 0 && i % 5 != 0) {
                printNumber.accept(i);
                num.release();
            } else if (i % 3 == 0 && i % 5 == 0) {
                fB.release();
            } else if (i % 3 == 0) {
                f.release();
            } else if (i % 5 == 0) {
                b.release();
            }
        }
    }
}

交替输出数字(信号量机制)

public class AppTest {
    private Semaphore first;
    private Semaphore second;

    public AppTest() {
        first = new Semaphore(1);
        second = new Semaphore(0);
    }

    /**
     * Rigorous Test :-)
     */
    @Test
    public void shouldAnswerWithTrue() throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 100; i++) {
                    if (i % 2 == 1) {
                        try {
                            first.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("thread1---" + i);
                        second.release();
                    }
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 100; i++) {
                    if (i % 2 == 0) {
                        try {
                            second.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("thread2---" + i);
                        first.release();
                    }
                }
            }
        });
        thread1.start();
        thread2.start();
        Thread.sleep(Integer.MAX_VALUE);
    }
}

举报

相关推荐

0 条评论