这篇文章将为大家详细讲解有关leetcode中怎么利用多线程交替打印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 次。
示例 1:
输入: n = 1
输出: "foobar"
解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。
示例 2:输入: n = 2
输出: "foobarfoobar"
解释: "foobar" 将被输出两次。
package com.lau.multithread.printinturn; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** 交替打印FooBar——方案1:传统方式 我们提供一个类: 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 次。 示例 1: 输入: n = 1 输出: "foobar" 解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。 示例 2: 输入: n = 2 输出: "foobarfoobar" 解释: "foobar" 将被输出两次。 */ class FooBar { private volatile int n; private volatile int flag = 0; public FooBar(int n) { this.n = n; } public void foo() { for (int i = 0; i < this.n; i++) { synchronized (this) { try { while(0 != this.flag) { this.wait(); } print("foo"); flag = 1; } catch (Exception e) { e.printStackTrace(); } finally { this.notify(); } } } } public void bar() { for (int i = 0; i < this.n; i++) { synchronized (this) { try { while(1 != this.flag) { this.wait(); } print("bar"); flag = 0; } catch (Exception e) { e.printStackTrace(); } finally { this.notify(); } } } } private void print(String target) { System.out.print(target); } } public class PrintInTurnDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(3); FooBar fooBar = new FooBar(5); threadPool.submit(() -> fooBar.foo()); threadPool.submit(() -> fooBar.bar()); threadPool.shutdown(); } }
package com.lau.multithread.printinturn; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** 交替打印FooBar——方案2:锁方式 我们提供一个类: 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 次。 示例 1: 输入: n = 1 输出: "foobar" 解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。 示例 2: 输入: n = 2 输出: "foobarfoobar" 解释: "foobar" 将被输出两次。 */ class FooBar2 { private final Lock lock = new ReentrantLock(); private final Condition fooCondition = lock.newCondition(); private final Condition barCondition = lock.newCondition(); private volatile int n; private volatile int flag = 0; public FooBar2(int n) { this.n = n; } public void foo() { for (int i = 0; i < this.n; i++) { try { lock.lock(); while(0 != this.flag) { fooCondition.await(); } print("foo"); flag = 1; } catch (Exception e) { e.printStackTrace(); } finally { barCondition.signal(); lock.unlock(); } } } public void bar() { for (int i = 0; i < this.n; i++) { try { lock.lock(); while(1 != this.flag) { barCondition.await(); } print("bar"); flag = 0; } catch (Exception e) { e.printStackTrace(); } finally { fooCondition.signal(); lock.unlock(); } } } private void print(String target) { System.out.print(target); } } public class PrintInTurnDemo2 { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(2); FooBar2 fooBar = new FooBar2(3); threadPool.submit(() -> fooBar.foo()); threadPool.submit(() -> fooBar.bar()); threadPool.shutdown(); } }
package com.lau.multithread.printinturn; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** 交替打印FooBar——方案3:信号量方式 我们提供一个类: 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 次。 示例 1: 输入: n = 1 输出: "foobar" 解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。 示例 2: 输入: n = 2 输出: "foobarfoobar" 解释: "foobar" 将被输出两次。 */ class FooBar3 { private final Semaphore fooSp = new Semaphore(1); private final Semaphore barSp = new Semaphore(0); private volatile int n; public FooBar3(int n) { this.n = n; } public void foo() { for (int i = 0; i < this.n; i++) { try { fooSp.acquire(); print("foo"); } catch (Exception e) { e.printStackTrace(); } finally { barSp.release(); } } } public void bar() { for (int i = 0; i < this.n; i++) { try { barSp.acquire(); print("bar"); } catch (Exception e) { e.printStackTrace(); } finally { fooSp.release(); } } } private void print(String target) { System.out.print(target); } } public class PrintInTurnDemo3 { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(2); FooBar3 fooBar = new FooBar3(5); threadPool.submit(() -> fooBar.foo()); threadPool.submit(() -> fooBar.bar()); threadPool.shutdown(); } }
输出:
foobarfoobarfoobarfoobarfoobar
关于leetcode中怎么利用多线程交替打印FooBar就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。