博客分类:多线程 Java 面试题 多线程 java thread Semaphore Condition最近发现公司有份笔试试卷中有道多线程的 题目: 有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…
这个最早好像是迅雷的面试题目吧,看到了然后就想重温一下这个题目的解决方法。
在本文中,给出了五种这个题目的解决方法:
- 使用sleep
- 使用synchronized, wait和notifyAll
- 使用Lock 和 Condition
- 使用Semaphore
- 使用AtomicInteger
下面依次给出每种解决方案的代码:
使用sleep
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
Java代码
文章图片
- 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
Java代码
文章图片
- 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
Java代码
文章图片
- 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();
- }
- }
- }
- }