leetcode中怎么实现多线程

本篇文章给大家分享的是有关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中怎么实现多线程,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注创新互联行业资讯频道。


当前题目:leetcode中怎么实现多线程
转载来于:http://myzitong.com/article/ghdhie.html