这篇文章将为大家详细讲解有关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就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/Howard2016/blog/5017968