溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

leetcode中怎么實現(xiàn)多線程

發(fā)布時間:2021-08-06 15:18:27 來源:億速云 閱讀:152 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關leetcode中怎么實現(xiàn)多線程,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

現(xiàn)在有兩種線程,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種線程來產生水分子。

存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。

氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。

這些線程應該三三成組突破屏障并能立即組合產生一個水分子。

你必須保證產生一個水分子所需線程的結合必須發(fā)生在下一個水分子產生之前。

換句話說:

如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
書寫滿足這些限制條件的氫、氧線程同步代碼。

 

示例 1:

輸入: "HOH"
輸出: "HHO"
解釋: "HOH" 和 "OHH" 依然都是有效解。
示例 2:

輸入: "OOHHHH"
輸出: "HHOHHO"
解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
 

提示:

輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
輸入字符串中的 “H” 總數(shù)將會是 2n 。
輸入字符串中的 “O” 總數(shù)將會是 n 。

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

package com.lau.multithread.h3o;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** 
 * 	H2O 生成——解法一:傳統(tǒng)方式
	現(xiàn)在有兩種線程,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種線程來產生水分子。
	
	存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。
	
	氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。
	
	這些線程應該三三成組突破屏障并能立即組合產生一個水分子。
	
	你必須保證產生一個水分子所需線程的結合必須發(fā)生在下一個水分子產生之前。
	
	換句話說:
	
	如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
	如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
	書寫滿足這些限制條件的氫、氧線程同步代碼。
	
	 
	
	示例 1:
	
	輸入: "HOH"
	輸出: "HHO"
	解釋: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	輸入: "OOHHHH"
	輸出: "HHOHHO"
	解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
	輸入字符串中的 “H” 總數(shù)將會是 2n 。
	輸入字符串中的 “O” 總數(shù)將會是 n 。
 * 
*/
class H2O{
	private volatile int h = 0;
	private volatile int o = 0;
	
	public synchronized void printH(Runnable printH) {
		try {
			while(2 == this.h) {
				this.wait();
			}
			
			printH.run();
			
			this.h++;
			
			if(2 == this.h && 1 == this.o) {
				h = 0;
				o = 0;
			}
			
			this.notify();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public synchronized void printO(Runnable printO) {
		try {
			while(1 == this.o) {
				this.wait();
			}
			
			printO.run();
			
			this.o++;
			
			if(2 == this.h && 1 == this.o) {
				h = 0;
				o = 0;
			}
			
			this.notify();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

public class PrintH2ODemo {

	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
		
		H2O h3o = new H2O();
		
		for(int i = 0; i < 5; i++) {
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printO(() -> System.out.print("O")));
		}
		
		threadPool.shutdown();
	}

}

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

package com.lau.multithread.h3o;

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;

/** 
 * 	H2O 生成——解法二:鎖方式
	現(xiàn)在有兩種線程,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種線程來產生水分子。
	
	存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。
	
	氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。
	
	這些線程應該三三成組突破屏障并能立即組合產生一個水分子。
	
	你必須保證產生一個水分子所需線程的結合必須發(fā)生在下一個水分子產生之前。
	
	換句話說:
	
	如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
	如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
	書寫滿足這些限制條件的氫、氧線程同步代碼。
	
	 
	
	示例 1:
	
	輸入: "HOH"
	輸出: "HHO"
	解釋: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	輸入: "OOHHHH"
	輸出: "HHOHHO"
	解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
	輸入字符串中的 “H” 總數(shù)將會是 2n 。
	輸入字符串中的 “O” 總數(shù)將會是 n 。
 * 
*/
class H2O2{
	private final Lock lock = new ReentrantLock();
	final Condition condition = lock.newCondition();
	
	private volatile int h = 0;
	private volatile int o = 0;
	
	public void printH(Runnable printH) {
		try {
			lock.lock();
			
			while(2 == this.h) {
				condition.await();
			}
			
			printH.run();
			
			this.h++;
			
			if(2 == this.h && 1 == this.o) {
				h = 0;
				o = 0;
			}
			
			condition.signal();
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			lock.unlock();
		}
	}
	
	public void printO(Runnable printO) {
		try {
			lock.lock();
			
			while(1 == this.o) {
				condition.await();
			}
			
			printO.run();
			
			this.o++;
			
			if(2 == this.h && 1 == this.o) {
				h = 0;
				o = 0;
			}
			
			condition.signal();
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			lock.unlock();
		}
	}
	
}

public class PrintH2ODemo2 {

	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
		
		H2O2 h3o = new H2O2();
		
		for(int i = 0; i < 5; i++) {
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printO(() -> System.out.print("O")));
		}
		
		threadPool.shutdown();
	}

}

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

package com.lau.multithread.h3o;

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;

/** 
 * 	H2O 生成——解法三:信號量方式(HHO)
	現(xiàn)在有兩種線程,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種線程來產生水分子。
	
	存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。
	
	氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。
	
	這些線程應該三三成組突破屏障并能立即組合產生一個水分子。
	
	你必須保證產生一個水分子所需線程的結合必須發(fā)生在下一個水分子產生之前。
	
	換句話說:
	
	如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
	如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
	書寫滿足這些限制條件的氫、氧線程同步代碼。
	
	 
	
	示例 1:
	
	輸入: "HOH"
	輸出: "HHO"
	解釋: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	輸入: "OOHHHH"
	輸出: "HHOHHO"
	解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
	輸入字符串中的 “H” 總數(shù)將會是 2n 。
	輸入字符串中的 “O” 總數(shù)將會是 n 。
 * 
*/
class H2O3{
	private final Semaphore hsp = new Semaphore(2);
	private final Semaphore osp = new Semaphore(0);
	
	public void printH(Runnable printH) {
		try {
			hsp.acquire();
			
			printH.run();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			osp.release();
		}
	}
	
	public void printO(Runnable printO) {
		try {
			osp.acquire(2);
			
			printO.run();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			hsp.release(2);
		}
	}
	
}

public class PrintH2ODemo3 {

	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
		
		H2O3 h3o = new H2O3();
		
		for(int i = 0; i < 5; i++) {
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printO(() -> System.out.print("O")));
		}
		
		threadPool.shutdown();
	}

}

實現(xiàn)方案4——信號量信號量  + 屏障(帶最終觸發(fā)行為)

package com.lau.multithread.h3o;

import java.util.concurrent.CyclicBarrier;
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;

/** 
 * 	H2O 生成——解法四:信號量  + 屏障(帶最終觸發(fā)行為)
	現(xiàn)在有兩種線程,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種線程來產生水分子。
	
	存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。
	
	氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。
	
	這些線程應該三三成組突破屏障并能立即組合產生一個水分子。
	
	你必須保證產生一個水分子所需線程的結合必須發(fā)生在下一個水分子產生之前。
	
	換句話說:
	
	如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
	如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
	書寫滿足這些限制條件的氫、氧線程同步代碼。
	
	 
	
	示例 1:
	
	輸入: "HOH"
	輸出: "HHO"
	解釋: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	輸入: "OOHHHH"
	輸出: "HHOHHO"
	解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
	輸入字符串中的 “H” 總數(shù)將會是 2n 。
	輸入字符串中的 “O” 總數(shù)將會是 n 。
 * 
*/
class H2O4{
	private final Semaphore hsp = new Semaphore(2);
	private final Semaphore osp = new Semaphore(1);
	
	private final CyclicBarrier cb = new CyclicBarrier(3, ()-> {
		hsp.release(2);
		osp.release(1);
	}); 
	
	public void printH(Runnable printH) {
		try {
			hsp.acquire();
			
			printH.run();
			
			cb.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void printO(Runnable printO) {
		try {
			osp.acquire();
			
			printO.run();
			
			cb.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

public class PrintH2ODemo4 {

	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
		
		H2O4 h3o = new H2O4();
		
		for(int i = 0; i < 5; i++) {
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printO(() -> System.out.print("O")));
		}
		
		threadPool.shutdown();
	}

}

實現(xiàn)方案5——信號量信號量  + 屏障

package com.lau.multithread.h3o;

import java.util.concurrent.CyclicBarrier;
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;

/** 
 * 	H2O 生成——解法四:信號量  + 屏障
	現(xiàn)在有兩種線程,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種線程來產生水分子。
	
	存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。
	
	氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。
	
	這些線程應該三三成組突破屏障并能立即組合產生一個水分子。
	
	你必須保證產生一個水分子所需線程的結合必須發(fā)生在下一個水分子產生之前。
	
	換句話說:
	
	如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
	如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
	書寫滿足這些限制條件的氫、氧線程同步代碼。
	
	 
	
	示例 1:
	
	輸入: "HOH"
	輸出: "HHO"
	解釋: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	輸入: "OOHHHH"
	輸出: "HHOHHO"
	解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
	輸入字符串中的 “H” 總數(shù)將會是 2n 。
	輸入字符串中的 “O” 總數(shù)將會是 n 。
 * 
*/
class H2O5{
	private final Semaphore hsp = new Semaphore(2);
	private final Semaphore osp = new Semaphore(1);
	
	private final CyclicBarrier cb = new CyclicBarrier(3); 
	
	public void printH(Runnable printH) {
		try {
			hsp.acquire();
			
			cb.await();
			
			printH.run();
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			hsp.release();
		}
	}
	
	public void printO(Runnable printO) {
		try {
			osp.acquire();
			
			cb.await();
			
			printO.run();
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			osp.release();
		}
	}
	
}

public class PrintH2ODemo5 {

	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
		
		H2O5 h3o = new H2O5();
		
		for(int i = 0; i < 5; i++) {
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printH(() -> System.out.print("H")));
			threadPool.execute(() -> h3o.printO(() -> System.out.print("O")));
		}
		
		threadPool.shutdown();
	}

}

輸出:

//隨機
HOHOHHOHHOHHOHH

以上就是leetcode中怎么實現(xiàn)多線程,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI