leetcode|多线程专题

1114. 按序打印

我们提供了一个类:

public class Foo {
  public void one() { print("one"); }
  public void two() { print("two"); }
  public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。

线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。

第一种方法 countdownlatch方法

class Foo {
        private CountDownLatch c2=new CountDownLatch(1);
        private CountDownLatch c3=new CountDownLatch(1);
        public Foo() {

        }

        public void first(Runnable printFirst) throws InterruptedException {

            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            c2.countDown();
        }

        public void second(Runnable printSecond) throws InterruptedException {
            c2.await();
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            c3.countDown();
        }

        public void third(Runnable printThird) throws InterruptedException {
            c3.await();
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();

        }
    }

第二种方法 CAS

class Foo {
        private AtomicInteger c2=new AtomicInteger(0);
        private AtomicInteger c3=new AtomicInteger(0);
        public Foo() {

        }

        public void first(Runnable printFirst) throws InterruptedException{

            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            c2.incrementAndGet();
        }

        public void second(Runnable printSecond) throws InterruptedException {
            // printSecond.run() outputs "second". Do not change or remove this line.
            while (c2.get()!=1){}
            printSecond.run();
            c3.incrementAndGet();
        }

        public void third(Runnable printThird) throws InterruptedException {
            // printThird.run() outputs "third". Do not change or remove this line.
            while (c3.get()!=1){}
            printThird.run();
        }
    }

第三种方法 信号量

class Foo {
        private Semaphore c2=new Semaphore(0);
        private Semaphore c3=new Semaphore(0);
        public Foo() {

        }

        public void first(Runnable printFirst) throws InterruptedException{

            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            c2.release();
        }

        public void second(Runnable printSecond) throws InterruptedException{
            // printSecond.run() outputs "second". Do not change or remove this line.
            c2.acquire();
            printSecond.run();
            c3.release();
        }

        public void third(Runnable printThird) throws InterruptedException {
            // printThird.run() outputs "third". Do not change or remove this line.
            c3.acquire();
            printThird.run();
        }
}

第四种方法 synchronized方法

class Foo {
        private final Object o=new Object();
        private int state=1;
        public Foo() {

        }

        public void first(Runnable printFirst) throws InterruptedException{

            // printFirst.run() outputs "first". Do not change or remove this line.
            synchronized (o) {
                printFirst.run();
                state=2;
                o.notifyAll();
            }
        }

        public void second(Runnable printSecond) throws InterruptedException{
            // printSecond.run() outputs "second". Do not change or remove this line.
            synchronized (o) {
                while (state!=2){
                    o.wait();
                }
                printSecond.run();
                state=3;
                o.notifyAll();
            }
        }

        public void third(Runnable printThird) throws InterruptedException {
            // printThird.run() outputs "third". Do not change or remove this line.
            synchronized (o) {
                while (state!=3){
                    o.wait();
                }
                printThird.run();
            }
        }
}

第五种方法 lock方法

class Foo {
        private ReentrantLock lock=new ReentrantLock();
        private Condition c2=lock.newCondition();
        private Condition c3=lock.newCondition();
        private int state=1;
        public Foo() {

        }

        public void first(Runnable printFirst) throws InterruptedException{

            // printFirst.run() outputs "first". Do not change or remove this line.
            try {
                lock.lock();
                printFirst.run();
                c2.signal();
                state=2;
            }finally {
                lock.unlock();
            }
        }

        public void second(Runnable printSecond) throws InterruptedException{
            // printSecond.run() outputs "second". Do not change or remove this line.
            try{
                lock.lock();
                while (state!=2){
                    c2.await();
                }
                printSecond.run();
                state=3;
                c3.signal();
            }finally {
                lock.unlock();
            }
        }

        public void third(Runnable printThird) throws InterruptedException {
            // printThird.run() outputs "third". Do not change or remove this line.
            try{
                lock.lock();
                while (state!=3){
                    c3.await();
                }
                printThird.run();
            }finally {
                lock.unlock();
            }
        }
    }

1115. 交替打印FooBar

我们提供一个类:

class FooBar {
  public void foo() {
    for (int i = 0; i < n; i++) {
      print("foo");
    }
  }

  public void bar() {
    for (int i = 0; i < n; i++) {
      print("bar");
    }
  }
}
两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。

请设计修改程序,以确保 "foobar" 被输出 n 次。

class FooBar {
        private int n;
        private Object lock=new Object();
        private int count=1;
        public FooBar(int n) {
            this.n = n;
        }

        public void foo(Runnable printFoo) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                synchronized (lock) {
                    while (count!=1)lock.wait();
                    // printFoo.run() outputs "foo". Do not change or remove this line.
                    printFoo.run();
                    lock.notifyAll();
                    count--;
                }
            }
        }

        public void bar(Runnable printBar) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                synchronized (lock) {
                    while (count!=0)lock.wait();
                    // printBar.run() outputs "bar". Do not change or remove this line.
                    printBar.run();
                    lock.notifyAll();
                    count++;
                }
            }
        }
    }

1116. 打印零与奇偶数

假设有这么一个类:

class ZeroEvenOdd {
  public ZeroEvenOdd(int n) { ... }      // 构造函数
  public void zero(printNumber) { ... }  // 仅打印出 0
  public void even(printNumber) { ... }  // 仅打印出 偶数
  public void odd(printNumber) { ... }   // 仅打印出 奇数
}
相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:

线程 A 将调用 zero(),它只输出 0 。
线程 B 将调用 even(),它只输出偶数。
线程 C 将调用 odd(),它只输出奇数。
每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。

class ZeroEvenOdd {
        private int n;
        private Semaphore zero=new Semaphore(1);
        private Semaphore odd=new Semaphore(0);
        private Semaphore even=new Semaphore(0);
        public ZeroEvenOdd(int n) {
            this.n = n;
        }

        // printNumber.accept(x) outputs "x", where x is an integer.
        public void zero(IntConsumer printNumber) throws InterruptedException {
            for(int i=1;i<=n;i++){
                zero.acquire();
                printNumber.accept(0);
                if((i&1)==1){
                    odd.release();
                }else{
                    even.release();
                }
            }
        }

        public void even(IntConsumer printNumber) throws InterruptedException {
            for(int i=2;i<=n;i+=2){
                even.acquire();
                printNumber.accept(i);
                zero.release();
            }

        }

        public void odd(IntConsumer printNumber) throws InterruptedException {
            for(int i=1;i<=n;i+=2) {
                odd.release();
                printNumber.accept(i);
                zero.release();
            }
        }
    }

1117. H2O 生成

每次获取一个H,需要释放一个O,O需要获取2个,同时H释放两个

    class H2O {
        private Semaphore h=new Semaphore(2);
        private Semaphore o=new Semaphore(0);
        public H2O() {

        }

        public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
            // releaseHydrogen.run() outputs "H". Do not change or remove this line.
            h.acquire();
            releaseHydrogen.run();
            o.release();
        }

        public void oxygen(Runnable releaseOxygen) throws InterruptedException {

            // releaseOxygen.run() outputs "O". Do not change or remove this line.
            o.acquire(2);
            releaseOxygen.run();
            h.release(2);
        }
    }

1195. 交替打印字符串

编写一个可以从 1 到 n 输出代表这个数字的字符串的程序,但是:

如果这个数字可以被 3 整除,输出 "fizz"。
如果这个数字可以被 5 整除,输出 "buzz"。
如果这个数字可以同时被 3 和 5 整除,输出 "fizzbuzz"。

class FizzBuzz {
        private int n;
        private ReentrantLock lock=new ReentrantLock();
        private Condition f=lock.newCondition();
        private Condition b=lock.newCondition();
        private Condition fb=lock.newCondition();
        private Condition nc=lock.newCondition();
        private boolean state=false;
        public FizzBuzz(int n) {
            this.n = n;
        }

        // printFizz.run() outputs "fizz".
        public void fizz(Runnable printFizz) throws InterruptedException {
            for(int i=3;i<=n;i+=3){
                lock.lock();
                try {
                    if (i % 5 != 0) {
                        while (!state){
                            f.await();
                        }
                        printFizz.run();
                        state=false;
                        nc.signal();
                    }
                }finally {
                    lock.unlock();
                }
            }
        }

        // printBuzz.run() outputs "buzz".
        public void buzz(Runnable printBuzz) throws InterruptedException {
            for(int i=5;i<=n;i+=5){
                lock.lock();
                try {
                    if(i%3!=0){
                        while (!state){
                            b.await();
                        }
                        printBuzz.run();
                        state=false;
                        nc.signal();
                    }
                }finally {
                    lock.unlock();
                }

            }
        }

        // printFizzBuzz.run() outputs "fizzbuzz".
        public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
            for(int i=15;i<=n;i+=15){
                lock.lock();
                try {
                    while (!state){
                        fb.await();
                    }
                    printFizzBuzz.run();
                    state=false;
                    nc.signal();
                }finally {
                    lock.unlock();
                }

            }
        }

        // printNumber.accept(x) outputs "x", where x is an integer.
        public void number(IntConsumer printNumber) throws InterruptedException {
            for(int i=1;i<=n;i++){
                lock.lock();
                try {
                    while (state){
                        nc.await();
                    }
                    if(i%3==0&&i%5==0){
                        fb.signal();
                        state=true;
                    }
                    else if(i%3==0){
                        f.signal();
                        state=true;
                    }else if(i%5==0){
                        b.signal();
                        state=true;
                    }else {
                        printNumber.accept(i);
                        nc.signal();
                    }
                }finally {
                    lock.unlock();
                }
            }
        }
    }

1226. 哲学家进餐

class DiningPhilosophers {
        private ReentrantLock[] locks=new ReentrantLock[]{
                new ReentrantLock(),
                new ReentrantLock(),
                new ReentrantLock(),
                new ReentrantLock(),
                new ReentrantLock()
        };
        private Semaphore eatLimit=new Semaphore(4);
        public DiningPhilosophers() {

        }

        // call the run() method of any runnable to execute its code
        public void wantsToEat(int philosopher,
                               Runnable pickLeftFork,
                               Runnable pickRightFork,
                               Runnable eat,
                               Runnable putLeftFork,
                               Runnable putRightFork) throws InterruptedException {
            int left=(philosopher+1)%5;
            int right=philosopher;
            eatLimit.acquire();
            locks[left].lock();
            locks[right].lock();
            pickLeftFork.run();
            pickRightFork.run();
            eat.run();
            putLeftFork.run();
            putRightFork.run();
            locks[left].unlock();
            locks[right].unlock();
            eatLimit.release();
        }
    }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值