最近
发现公司有份笔试试卷中有道多
线程的
题目:
有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…
这个最早好像是迅雷的面试题目吧,看到了然后就想重温一下这个题目的
解决方法。
在本文中,给出了五种这个题目的解决方法:
- 使用sleep
- 使用synchronized, wait和notifyAll
- 使用Lock 和 Condition
- 使用Semaphore
- 使用AtomicInteger
下面依次给出每种解决方案的代码:
使用sleep
class="java">package my.thread.test;
/**
 * @author Eric
 */
public class SleepExample extends Thread {
	private static int currentCount = 0;
	public SleepExample(String name) {
		this.setName(name);
	}
	@Override
	public void run() {
		while (currentCount < 30) {
			switch (currentCount % 3) {
			case 0:
				if ("A".equals(getName())) {
					printAndIncrease();
				}
				break;
			case 1:
				if ("B".equals(getName())) {
					printAndIncrease();
				}
				break;
			case 2:
				if ("C".equals(getName())) {
					printAndIncrease();
				}
				break;
			}
		}
	}
	private void printAndIncrease() {
		print();
		increase();
	}
	private void print() {
		System.out.println(getName());
		if ("C".equals(getName())) {
			System.out.println();
		}
	}
	private void increase() {
		currentCount++;
	}
	public static void main(String[] args) {
		new SleepExample("A").start();
		new SleepExample("B").start();
		new SleepExample("C").start();
	}
}
使用synchronized, wait和notifyAll
package my.thread.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PrintThreadExample {
	public static void main(String[] args) {
		PrintThreadExample example = new PrintThreadExample();
		LetterPrinter letterPrinter = example.new LetterPrinter();
		ExecutorService service = Executors.newFixedThreadPool(3);
		service.execute(example.new PrintRunnable(letterPrinter, 'A'));
		service.execute(example.new PrintRunnable(letterPrinter, 'B'));
		service.execute(example.new PrintRunnable(letterPrinter, 'C'));
		service.shutdown();
	}
	private class LetterPrinter {
		private char letter = 'A';
		public void print() {
			System.out.println(letter);
			if ('C' == letter) {
				System.out.println();
			}
		}
		public void nextLetter() {
			switch (letter) {
			case 'A':
				letter = 'B';
				break;
			case 'B':
				letter = 'C';
				break;
			case 'C':
				letter = 'A';
				break;
			}
		}
		/**
		 * @return the letter
		 */
		public char getLetter() {
			return letter;
		}
	}
	private class PrintRunnable implements Runnable {
		private LetterPrinter letterPrinter = null;
		private char letter = ' ';
		/**
		 * @param letterPrinter
		 * @param letter
		 */
		public PrintRunnable(LetterPrinter letterPrinter, char letter) {
			super();
			this.letterPrinter = letterPrinter;
			this.letter = letter;
		}
		public void run() {
			for (int i = 0; i < 10; i++) {
				synchronized (letterPrinter) {
					while (letter != letterPrinter.getLetter()) {
						try {
							letterPrinter.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					letterPrinter.print();
					letterPrinter.nextLetter();
					letterPrinter.notifyAll();
				}
			}
		}
	}
}
JDK 1.5 引入J.U.C包之后,也给我们提供了更多实现多线程程序的选择: Condition, 原子类AtomicInteger以及Semaphore等。
使用Lock 和 Condition
package my.thread.test;
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;
import java.util.logging.Logger;
/**
 * 题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…
 * 
 * 本程序采用Lock和Condition来实现。
 * 
 * @author Eric
 * 
 */
public class ConditionExample {
	private Lock lock = new ReentrantLock();
	private Condition conditionA = lock.newCondition();
	private Condition conditionB = lock.newCondition();
	private Condition conditionC = lock.newCondition();
	/** 当前线程的名字 */
	private char currentThreadName = 'A';
	private static final Logger logger = Logger
			.getLogger("my.thread.test.OrderPrintTest");
	public static void main(String[] args) {
		ConditionExample ce = new ConditionExample();
		ExecutorService service = Executors.newFixedThreadPool(3);
		service.execute(ce.new ThreadA());
		service.execute(ce.new ThreadB());
		service.execute(ce.new ThreadC());
		service.shutdown();
	}
	private class ThreadA implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				lock.lock();
				try {
					while (currentThreadName != 'A') {
						try {
							/*
							 * 如果当前线程名字不是A,那么ThreadA就处理等待状态
							 */
							conditionA.await();
						} catch (InterruptedException e) {
							logger.severe(e.getLocalizedMessage());
						}
					}
					/*
					 * 打印出第几遍以及A信息
					 */
					System.out.println(String.format("第%d遍", i + 1));
					System.out.println("A");
					/*
					 * 将当前线程名置为B, 然后通知ThreadB执行
					 */
					currentThreadName = 'B';
					conditionB.signal();
				} finally {
					lock.unlock();
				}
			}
		}
	}
	private class ThreadB implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				lock.lock();
				try {
					while (currentThreadName != 'B') {
						try {
							/*
							 * 如果当前线程名字不是B,那么ThreadB就处理等待状态
							 */
							conditionB.await();
						} catch (InterruptedException e) {
							logger.severe(e.getLocalizedMessage());
						}
					}
					/*
					 * 打印信息B
					 */
					System.out.println("B");
					/*
					 * 将当前线程值置为C 并通过ThreadC来执行
					 */
					currentThreadName = 'C';
					conditionC.signal();
				} finally {
					lock.unlock();
				}
			}
		}
	}
	private class ThreadC implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				lock.lock();
				try {
					while (currentThreadName != 'C') {
						try {
							/*
							 * 如果当前线程名字不是C,那么ThreadC就处理等待状态
							 */
							conditionC.await();
						} catch (InterruptedException e) {
							logger.severe(e.getLocalizedMessage());
						}
					}
					/*
					 * 打印信息C
					 */
					System.out.println("C");
					System.out.println();
					/*
					 * 将当前线程值置为A 并通过ThreadA来执行
					 */
					currentThreadName = 'A';
					conditionA.signal();
				} finally {
					lock.unlock();
				}
			}
		}
	}
}
使用Semaphore
package my.thread.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoresExample {
	private Semaphore semaphoresA = new Semaphore(1);
	private Semaphore semaphoresB = new Semaphore(0);
	private Semaphore semaphoresC = new Semaphore(0);
	public static void main(String[] args) {
		SemaphoresExample example = new SemaphoresExample();
		ExecutorService service = Executors.newFixedThreadPool(3);
		service.execute(example.new RunnableA());
		service.execute(example.new RunnableB());
		service.execute(example.new RunnableC());
		service.shutdown();
	}
	private class RunnableA implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				try {
					semaphoresA.acquire();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(String.format("第%d遍", i + 1));
				System.out.println("A");
				semaphoresB.release();
			}
		}
	}
	private class RunnableB implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				try {
					semaphoresB.acquire();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("B");
				semaphoresC.release();
			}
		}
	}
	private class RunnableC implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				try {
					semaphoresC.acquire();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("C");
				System.out.println();
				semaphoresA.release();
			}
		}
	}
}
使用AtomicInteger
package my.thread.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerExample {
	private AtomicInteger sycValue = new AtomicInteger(0);
	private static final int MAX_SYC_VALUE = 3 * 10;
	public static void main(String[] args) {
		AtomicIntegerExample example = new AtomicIntegerExample();
		ExecutorService service = Executors.newFixedThreadPool(3);
		service.execute(example.new RunnableA());
		service.execute(example.new RunnableB());
		service.execute(example.new RunnableC());
		service.shutdown();
	}
	private class RunnableA implements Runnable {
		public void run() {
			while (sycValue.get() < MAX_SYC_VALUE) {
				if (sycValue.get() % 3 == 0) {
					System.out.println(String.format("第%d遍",
							sycValue.get() / 3 + 1));
					System.out.println("A");
					sycValue.getAndIncrement();
				}
			}
		}
	}
	private class RunnableB implements Runnable {
		public void run() {
			while (sycValue.get() < MAX_SYC_VALUE) {
				if (sycValue.get() % 3 == 1) {
					System.out.println("B");
					sycValue.getAndIncrement();
				}
			}
		}
	}
	private class RunnableC implements Runnable {
		public void run() {
			while (sycValue.get() < MAX_SYC_VALUE) {
				if (sycValue.get() % 3 == 2) {
					System.out.println("C");
					System.out.println();
					sycValue.getAndIncrement();
				}
			}
		}
	}
}
转载请注明出处http://mouselearnjava.iteye.com/blog/1949228