leetcode中怎么利用多線程交替打印FooBar

這篇文章將為大家詳細講解有關(guān)leetcode中怎么利用多線程交替打印FooBar,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

站在用戶的角度思考問題,與客戶深入溝通,找到定陶網(wǎng)站設(shè)計與定陶網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:網(wǎng)站制作、網(wǎng)站設(shè)計、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名與空間、虛擬主機、企業(yè)郵箱。業(yè)務(wù)覆蓋定陶地區(qū)。

我們提供一個類:

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() 方法。

請設(shè)計修改程序,以確保 "foobar" 被輸出 n 次。

 

示例 1:

輸入: n = 1
輸出: "foobar"
解釋: 這里有兩個線程被異步啟動。其中一個調(diào)用 foo() 方法, 另一個調(diào)用 bar() 方法,"foobar" 將被輸出一次。
示例 2:

輸入: n = 2
輸出: "foobarfoobar"
解釋: "foobar" 將被輸出兩次。

實現(xiàn)方案1——傳統(tǒng)方式

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() 方法。
	
	請設(shè)計修改程序,以確保 "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();
	}

}

實現(xiàn)方案2——鎖方式

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() 方法。
	
	請設(shè)計修改程序,以確保 "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();
	}

}

實現(xiàn)方案3——信號量

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() 方法。
	
	請設(shè)計修改程序,以確保 "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

關(guān)于leetcode中怎么利用多線程交替打印FooBar就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

本文題目:leetcode中怎么利用多線程交替打印FooBar
標題網(wǎng)址:http://muchs.cn/article18/ghejdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)虛擬主機、企業(yè)網(wǎng)站制作、云服務(wù)器、、動態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司