多线程打印abc

来源:互联网 发布:新三板源码 编辑:程序博客网 时间:2024/06/06 18:38

面试题--三个线程循环打印ABC10次的几种解决方法

    博客分类: 
  • 多线程
  • Java
  • 面试题
多线程javathreadSemaphoreCondition 
最近发现公司有份笔试试卷中有道多线程的题目有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC… 

这个最早好像是迅雷的面试题目吧,看到了然后就想重温一下这个题目的解决方法。 

在本文中,给出了五种这个题目的解决方法: 

  • 使用sleep
  • 使用synchronized, wait和notifyAll
  • 使用Lock 和 Condition
  • 使用Semaphore
  • 使用AtomicInteger


下面依次给出每种解决方案的代码: 

使用sleep 
Java代码  收藏代码
  1. package my.thread.test;  
  2.   
  3. /** 
  4.  * @author Eric 
  5.  */  
  6. public class SleepExample extends Thread {  
  7.   
  8.     private static int currentCount = 0;  
  9.   
  10.     public SleepExample(String name) {  
  11.         this.setName(name);  
  12.     }  
  13.   
  14.     @Override  
  15.     public void run() {  
  16.         while (currentCount < 30) {  
  17.             switch (currentCount % 3) {  
  18.             case 0:  
  19.                 if ("A".equals(getName())) {  
  20.                     printAndIncrease();  
  21.                 }  
  22.                 break;  
  23.             case 1:  
  24.                 if ("B".equals(getName())) {  
  25.                     printAndIncrease();  
  26.                 }  
  27.                 break;  
  28.             case 2:  
  29.                 if ("C".equals(getName())) {  
  30.                     printAndIncrease();  
  31.                 }  
  32.                 break;  
  33.             }  
  34.         }  
  35.   
  36.     }  
  37.   
  38.     private void printAndIncrease() {  
  39.         print();  
  40.         increase();  
  41.     }  
  42.   
  43.     private void print() {  
  44.         System.out.println(getName());  
  45.         if ("C".equals(getName())) {  
  46.             System.out.println();  
  47.         }  
  48.     }  
  49.   
  50.     private void increase() {  
  51.         currentCount++;  
  52.     }  
  53.   
  54.     public static void main(String[] args) {  
  55.         new SleepExample("A").start();  
  56.         new SleepExample("B").start();  
  57.         new SleepExample("C").start();  
  58.     }  
  59.   
  60. }  


使用synchronized, wait和notifyAll 

Java代码  收藏代码
  1. package my.thread.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class PrintThreadExample {  
  7.   
  8.     public static void main(String[] args) {  
  9.         PrintThreadExample example = new PrintThreadExample();  
  10.   
  11.         LetterPrinter letterPrinter = example.new LetterPrinter();  
  12.   
  13.         ExecutorService service = Executors.newFixedThreadPool(3);  
  14.   
  15.         service.execute(example.new PrintRunnable(letterPrinter, 'A'));  
  16.         service.execute(example.new PrintRunnable(letterPrinter, 'B'));  
  17.         service.execute(example.new PrintRunnable(letterPrinter, 'C'));  
  18.   
  19.         service.shutdown();  
  20.     }  
  21.   
  22.     private class LetterPrinter {  
  23.         private char letter = 'A';  
  24.   
  25.         public void print() {  
  26.             System.out.println(letter);  
  27.             if ('C' == letter) {  
  28.                 System.out.println();  
  29.             }  
  30.         }  
  31.   
  32.         public void nextLetter() {  
  33.             switch (letter) {  
  34.             case 'A':  
  35.                 letter = 'B';  
  36.                 break;  
  37.             case 'B':  
  38.                 letter = 'C';  
  39.                 break;  
  40.             case 'C':  
  41.                 letter = 'A';  
  42.                 break;  
  43.             }  
  44.         }  
  45.   
  46.         /** 
  47.          * @return the letter 
  48.          */  
  49.         public char getLetter() {  
  50.             return letter;  
  51.         }  
  52.   
  53.     }  
  54.   
  55.     private class PrintRunnable implements Runnable {  
  56.   
  57.         private LetterPrinter letterPrinter = null;  
  58.   
  59.         private char letter = ' ';  
  60.   
  61.         /** 
  62.          * @param letterPrinter 
  63.          * @param letter 
  64.          */  
  65.         public PrintRunnable(LetterPrinter letterPrinter, char letter) {  
  66.             super();  
  67.             this.letterPrinter = letterPrinter;  
  68.             this.letter = letter;  
  69.         }  
  70.   
  71.         public void run() {  
  72.             for (int i = 0; i < 10; i++) {  
  73.                 synchronized (letterPrinter) {  
  74.                     while (letter != letterPrinter.getLetter()) {  
  75.                         try {  
  76.                             letterPrinter.wait();  
  77.                         } catch (InterruptedException e) {  
  78.                             // TODO Auto-generated catch block  
  79.                             e.printStackTrace();  
  80.                         }  
  81.                     }  
  82.   
  83.                     letterPrinter.print();  
  84.                     letterPrinter.nextLetter();  
  85.                     letterPrinter.notifyAll();  
  86.   
  87.                 }  
  88.             }  
  89.   
  90.         }  
  91.   
  92.     }  
  93.   
  94. }  


JDK 1.5 引入J.U.C包之后,也给我们提供了更多实现多线程程序的选择: Condition, 原子类AtomicInteger以及Semaphore等。 


使用Lock 和 Condition
 
Java代码  收藏代码
  1. package my.thread.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5. import java.util.concurrent.locks.Condition;  
  6. import java.util.concurrent.locks.Lock;  
  7. import java.util.concurrent.locks.ReentrantLock;  
  8. import java.util.logging.Logger;  
  9.   
  10. /** 
  11.  * 题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC… 
  12.  *  
  13.  * 本程序采用Lock和Condition来实现。 
  14.  *  
  15.  * @author Eric 
  16.  *  
  17.  */  
  18. public class ConditionExample {  
  19.   
  20.     private Lock lock = new ReentrantLock();  
  21.   
  22.     private Condition conditionA = lock.newCondition();  
  23.     private Condition conditionB = lock.newCondition();  
  24.     private Condition conditionC = lock.newCondition();  
  25.   
  26.     /** 当前线程的名字 */  
  27.     private char currentThreadName = 'A';  
  28.   
  29.     private static final Logger logger = Logger  
  30.             .getLogger("my.thread.test.OrderPrintTest");  
  31.   
  32.     public static void main(String[] args) {  
  33.   
  34.         ConditionExample ce = new ConditionExample();  
  35.   
  36.         ExecutorService service = Executors.newFixedThreadPool(3);  
  37.         service.execute(ce.new ThreadA());  
  38.         service.execute(ce.new ThreadB());  
  39.         service.execute(ce.new ThreadC());  
  40.   
  41.         service.shutdown();  
  42.     }  
  43.   
  44.     private class ThreadA implements Runnable {  
  45.         public void run() {  
  46.   
  47.             for (int i = 0; i < 10; i++) {  
  48.                 lock.lock();  
  49.                 try {  
  50.                     while (currentThreadName != 'A') {  
  51.                         try {  
  52.                             /* 
  53.                              * 如果当前线程名字不是A,那么ThreadA就处理等待状态 
  54.                              */  
  55.                             conditionA.await();  
  56.                         } catch (InterruptedException e) {  
  57.                             logger.severe(e.getLocalizedMessage());  
  58.                         }  
  59.                     }  
  60.   
  61.                     /* 
  62.                      * 打印出第几遍以及A信息 
  63.                      */  
  64.                     System.out.println(String.format("第%d遍", i + 1));  
  65.                     System.out.println("A");  
  66.   
  67.                     /* 
  68.                      * 将当前线程名置为B, 然后通知ThreadB执行 
  69.                      */  
  70.                     currentThreadName = 'B';  
  71.                     conditionB.signal();  
  72.   
  73.                 } finally {  
  74.                     lock.unlock();  
  75.                 }  
  76.             }  
  77.         }  
  78.   
  79.     }  
  80.   
  81.     private class ThreadB implements Runnable {  
  82.         public void run() {  
  83.             for (int i = 0; i < 10; i++) {  
  84.                 lock.lock();  
  85.                 try {  
  86.                     while (currentThreadName != 'B') {  
  87.                         try {  
  88.                             /* 
  89.                              * 如果当前线程名字不是B,那么ThreadB就处理等待状态 
  90.                              */  
  91.                             conditionB.await();  
  92.                         } catch (InterruptedException e) {  
  93.                             logger.severe(e.getLocalizedMessage());  
  94.                         }  
  95.                     }  
  96.   
  97.                     /* 
  98.                      * 打印信息B 
  99.                      */  
  100.                     System.out.println("B");  
  101.   
  102.                     /* 
  103.                      * 将当前线程值置为C 并通过ThreadC来执行 
  104.                      */  
  105.                     currentThreadName = 'C';  
  106.                     conditionC.signal();  
  107.   
  108.                 } finally {  
  109.                     lock.unlock();  
  110.                 }  
  111.             }  
  112.   
  113.         }  
  114.   
  115.     }  
  116.   
  117.     private class ThreadC implements Runnable {  
  118.   
  119.         public void run() {  
  120.             for (int i = 0; i < 10; i++) {  
  121.                 lock.lock();  
  122.                 try {  
  123.                     while (currentThreadName != 'C') {  
  124.                         try {  
  125.                             /* 
  126.                              * 如果当前线程名字不是C,那么ThreadC就处理等待状态 
  127.                              */  
  128.                             conditionC.await();  
  129.                         } catch (InterruptedException e) {  
  130.                             logger.severe(e.getLocalizedMessage());  
  131.                         }  
  132.                     }  
  133.   
  134.                     /* 
  135.                      * 打印信息C 
  136.                      */  
  137.                     System.out.println("C");  
  138.                     System.out.println();  
  139.   
  140.                     /* 
  141.                      * 将当前线程值置为A 并通过ThreadA来执行 
  142.                      */  
  143.                     currentThreadName = 'A';  
  144.                     conditionA.signal();  
  145.   
  146.                 } finally {  
  147.                     lock.unlock();  
  148.                 }  
  149.   
  150.             }  
  151.         }  
  152.     }  
  153. }  



使用Semaphore 
Java代码  收藏代码
  1. package my.thread.test;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5. import java.util.concurrent.Semaphore;  
  6.   
  7. public class SemaphoresExample {  
  8.   
  9.     private Semaphore semaphoresA = new Semaphore(1);  
  10.     private Semaphore semaphoresB = new Semaphore(0);  
  11.     private Semaphore semaphoresC = new Semaphore(0);  
  12.   
  13.     public static void main(String[] args) {  
  14.         SemaphoresExample example = new SemaphoresExample();  
  15.         ExecutorService service = Executors.newFixedThreadPool(3);  
  16.   
  17.         service.execute(example.new RunnableA());  
  18.         service.execute(example.new RunnableB());  
  19.         service.execute(example.new RunnableC());  
  20.   
  21.         service.shutdown();  
  22.     }  
  23.   
  24.     private class RunnableA implements Runnable {  
  25.   
  26.         public void run() {  
  27.   
  28.             for (int i = 0; i < 10; i++) {  
  29.                 try {  
  30.                     semaphoresA.acquire();  
  31.                 } catch (InterruptedException e) {  
  32.                     // TODO Auto-generated catch block  
  33.                     e.printStackTrace();  
  34.                 }  
  35.                 System.out.println(String.format("第%d遍", i + 1));  
  36.                 System.out.println("A");  
  37.                 semaphoresB.release();  
  38.   
  39.             }  
  40.         }  
  41.     }  
  42.   
  43.     private class RunnableB implements Runnable {  
  44.   
  45.         public void run() {  
  46.   
  47.             for (int i = 0; i < 10; i++) {  
  48.                 try {  
  49.                     semaphoresB.acquire();  
  50.                 } catch (InterruptedException e) {  
  51.                     // TODO Auto-generated catch block  
  52.                     e.printStackTrace();  
  53.                 }  
  54.                 System.out.println("B");  
  55.                 semaphoresC.release();  
  56.             }  
  57.   
  58.         }  
  59.     }  
  60.   
  61.     private class RunnableC implements Runnable {  
  62.   
  63.         public void run() {  
  64.   
  65.             for (int i = 0; i < 10; i++) {  
  66.                 try {  
  67.                     semaphoresC.acquire();  
  68.                 } catch (InterruptedException e) {  
  69.                     // TODO Auto-generated catch block  
  70.                     e.printStackTrace();  
  71.                 }  
  72.                 System.out.println("C");  
  73.                 System.out.println();  
  74.   
  75.                 semaphoresA.release();  
  76.             }  
  77.         }  
  78.     }  
  79. }