温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

leetcode中怎么实现多线程

发布时间:2021-08-06 15:18:27 来源:亿速云 阅读:133 作者:Leah 栏目:编程语言

本篇文章给大家分享的是有关leetcode中怎么实现多线程,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。

存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。

氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。

这些线程应该三三成组突破屏障并能立即组合产生一个水分子。

你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。

换句话说:

如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
书写满足这些限制条件的氢、氧线程同步代码。

 

示例 1:

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

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

提示:

输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
输入字符串中的 “H” 总数将会是 2n 。
输入字符串中的 “O” 总数将会是 n 。

实现方案1——传统方式

package com.lau.multithread.h3o;

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

/** 
 * 	H2O 生成——解法一:传统方式
	现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
	
	存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
	
	氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
	
	这些线程应该三三成组突破屏障并能立即组合产生一个水分子。
	
	你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。
	
	换句话说:
	
	如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
	如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
	书写满足这些限制条件的氢、氧线程同步代码。
	
	 
	
	示例 1:
	
	输入: "HOH"
	输出: "HHO"
	解释: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	输入: "OOHHHH"
	输出: "HHOHHO"
	解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
	输入字符串中的 “H” 总数将会是 2n 。
	输入字符串中的 “O” 总数将会是 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();
	}

}

实现方案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 生成——解法二:锁方式
	现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
	
	存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
	
	氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
	
	这些线程应该三三成组突破屏障并能立即组合产生一个水分子。
	
	你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。
	
	换句话说:
	
	如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
	如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
	书写满足这些限制条件的氢、氧线程同步代码。
	
	 
	
	示例 1:
	
	输入: "HOH"
	输出: "HHO"
	解释: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	输入: "OOHHHH"
	输出: "HHOHHO"
	解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
	输入字符串中的 “H” 总数将会是 2n 。
	输入字符串中的 “O” 总数将会是 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();
	}

}

实现方案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)
	现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
	
	存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
	
	氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
	
	这些线程应该三三成组突破屏障并能立即组合产生一个水分子。
	
	你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。
	
	换句话说:
	
	如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
	如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
	书写满足这些限制条件的氢、氧线程同步代码。
	
	 
	
	示例 1:
	
	输入: "HOH"
	输出: "HHO"
	解释: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	输入: "OOHHHH"
	输出: "HHOHHO"
	解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
	输入字符串中的 “H” 总数将会是 2n 。
	输入字符串中的 “O” 总数将会是 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();
	}

}

实现方案4——信号量信号量  + 屏障(带最终触发行为)

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 生成——解法四:信号量  + 屏障(带最终触发行为)
	现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
	
	存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
	
	氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
	
	这些线程应该三三成组突破屏障并能立即组合产生一个水分子。
	
	你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。
	
	换句话说:
	
	如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
	如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
	书写满足这些限制条件的氢、氧线程同步代码。
	
	 
	
	示例 1:
	
	输入: "HOH"
	输出: "HHO"
	解释: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	输入: "OOHHHH"
	输出: "HHOHHO"
	解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
	输入字符串中的 “H” 总数将会是 2n 。
	输入字符串中的 “O” 总数将会是 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();
	}

}

实现方案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 生成——解法四:信号量  + 屏障
	现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
	
	存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
	
	氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
	
	这些线程应该三三成组突破屏障并能立即组合产生一个水分子。
	
	你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。
	
	换句话说:
	
	如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
	如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
	书写满足这些限制条件的氢、氧线程同步代码。
	
	 
	
	示例 1:
	
	输入: "HOH"
	输出: "HHO"
	解释: "HOH" 和 "OHH" 依然都是有效解。
	示例 2:
	
	输入: "OOHHHH"
	输出: "HHOHHO"
	解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
	 
	
	提示:
	
	输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
	输入字符串中的 “H” 总数将会是 2n 。
	输入字符串中的 “O” 总数将会是 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中怎么实现多线程,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI