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

这篇文章将为大家详细讲解有关leetcode中怎么利用多线程交替打印FooBar,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

站在用户的角度思考问题,与客户深入沟通,找到定陶网站设计与定陶网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:网站制作、网站设计、企业官网、英文网站、手机端网站、网站推广、域名与空间、虚拟主机、企业邮箱。业务覆盖定陶地区。

我们提供一个类:

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 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。

请设计修改程序,以确保 "foobar" 被输出 n 次。

 

示例 1:

输入: n = 1
输出: "foobar"
解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。
示例 2:

输入: n = 2
输出: "foobarfoobar"
解释: "foobar" 将被输出两次。

实现方案1——传统方式

package com.lau.multithread.printinturn;

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


/** 
	交替打印FooBar——方案1:传统方式
	我们提供一个类:
	
	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 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
	
	请设计修改程序,以确保 "foobar" 被输出 n 次。
	
	
	示例 1:
	
	输入: n = 1
	输出: "foobar"
	解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 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();
	}

}

实现方案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 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
	
	请设计修改程序,以确保 "foobar" 被输出 n 次。
	
	
	示例 1:
	
	输入: n = 1
	输出: "foobar"
	解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 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();
	}

}

实现方案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 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
	
	请设计修改程序,以确保 "foobar" 被输出 n 次。
	
	
	示例 1:
	
	输入: n = 1
	输出: "foobar"
	解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 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就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。


标题名称:leetcode中怎么利用多线程交替打印FooBar
分享地址:http://scyanting.com/article/ghejdp.html