您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關leetcode中怎么利用多線程交替打印FooBar,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
我們提供一個類:
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 實例。其中一個線程將會調(diào)用 foo() 方法,另一個線程將會調(diào)用 bar() 方法。請設計修改程序,以確保 "foobar" 被輸出 n 次。
示例 1:
輸入: n = 1
輸出: "foobar"
解釋: 這里有兩個線程被異步啟動。其中一個調(diào)用 foo() 方法, 另一個調(diào)用 bar() 方法,"foobar" 將被輸出一次。
示例 2:輸入: n = 2
輸出: "foobarfoobar"
解釋: "foobar" 將被輸出兩次。
package com.lau.multithread.printinturn; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** 交替打印FooBar——方案1:傳統(tǒng)方式 我們提供一個類: 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 實例。其中一個線程將會調(diào)用 foo() 方法,另一個線程將會調(diào)用 bar() 方法。 請設計修改程序,以確保 "foobar" 被輸出 n 次。 示例 1: 輸入: n = 1 輸出: "foobar" 解釋: 這里有兩個線程被異步啟動。其中一個調(diào)用 foo() 方法, 另一個調(diào)用 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 實例。其中一個線程將會調(diào)用 foo() 方法,另一個線程將會調(diào)用 bar() 方法。 請設計修改程序,以確保 "foobar" 被輸出 n 次。 示例 1: 輸入: n = 1 輸出: "foobar" 解釋: 這里有兩個線程被異步啟動。其中一個調(diào)用 foo() 方法, 另一個調(diào)用 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 實例。其中一個線程將會調(diào)用 foo() 方法,另一個線程將會調(diào)用 bar() 方法。 請設計修改程序,以確保 "foobar" 被輸出 n 次。 示例 1: 輸入: n = 1 輸出: "foobar" 解釋: 這里有兩個線程被異步啟動。其中一個調(diào)用 foo() 方法, 另一個調(diào)用 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就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。