Java面试题之多线程打印
概述
作为程序员经常在面试的时候遇到多线程的问题,我印象比较深刻的就是下面这道题:写两个线程,一个线程打印 1~52,另一个线程打印字母A-Z。打印顺序为12A34B56C……5152Z。看这个题目已经说得很清楚了,要用两个线程交替打印出12A....Z,我相信如每个线程单独打印的话肯定没问题,但是要交替打印,就需要两个线程互相合作,就需要通信。
代码实现
方法一
1 package com.cfxmn.springboot.springbootDemo.test; 2 3 // 使用多线程打印12A34B.......5152Z 4 public class MainTest2 { 5 public static void main(String[] args) { 6 Object obj = new Object(); // 共享资源,实现线程间的通信 7 Thread printNum = new Thread(new PrintNum(obj)); 8 Thread printChar = new Thread(new PrintChar(obj)); 9 printNum.start(); 10 printChar.start(); 11 } 12 } 13 14 // 打印数字 15 class PrintNum implements Runnable { 16 17 private Object object; 18 19 public PrintNum (Object obj) { 20 this.object = obj; 21 } 22 23 @Override 24 public void run() { 25 synchronized (object) { 26 for (int i=1;i<=52;i++) { 27 System.out.print(i); 28 if (i % 2 == 0) { 29 object.notifyAll(); // 先唤醒所有线程 30 try { 31 object.wait(); // 阻塞当前线程 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 } 36 } 37 } 38 } 39 40 } 41 42 // 打印字母 43 class PrintChar implements Runnable { 44 45 private Object object; 46 47 public PrintChar (Object obj) { 48 this.object = obj; 49 } 50 51 @Override 52 public void run() { 53 synchronized (object) { 54 for (int i=65;i<=90;i++) { 55 System.out.print((char)i); 56 object.notifyAll(); // 先唤醒所有线程 57 try { 58 object.wait(); // 阻塞当前线程 59 } catch (InterruptedException e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 } 65 66 }
运行结果:
12A34B56C78D910E1112F1314G1516H1718I1920J2122K2324L2526M2728N2930O3132P3334Q3536R3738S3940T4142U4344V4546W4748X4950Y5152Z
上面我是使用了wait,notifyAll,synchronized实现的,是不是还有其他的实现方法呢?
方法二
1 package com.cfxmn.springboot.springbootDemo.test; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 //使用多线程打印12A34B.......5152Z 8 public class MainTest3 { 9 10 private Lock lock = new ReentrantLock(); 11 private Condition printNum = lock.newCondition(); 12 private Condition printchar = lock.newCondition(); 13 14 public static void main(String[] args) { 15 MainTest3 test = new MainTest3(); 16 Thread printNum = new Thread(test.new PrintNumt()); 17 Thread printChar = new Thread(test.new PrintChart()); 18 printChar.start(); 19 printNum.start(); 20 21 } 22 23 //打印数字 24 class PrintNumt implements Runnable { 25 26 @Override 27 public void run() { 28 29 for (int i = 1; i <= 52; i++) { 30 lock.lock(); 31 try { 32 printchar.signalAll(); 33 System.out.print(i); 34 if (i % 2 == 0) { 35 printNum.await(); 36 } 37 } catch (Exception e) { 38 e.printStackTrace(); 39 } finally { 40 lock.unlock(); 41 } 42 } 43 } 44 45 } 46 47 //打印字母 48 class PrintChart implements Runnable { 49 50 @Override 51 public void run() { 52 53 for (int i = 0; i < 26; i++) { 54 lock.lock(); 55 try { 56 printNum.signalAll(); 57 System.out.print((char)(i + 'A')); 58 printchar.await(); 59 } catch (Exception e) { 60 e.printStackTrace(); 61 62 } finally { 63 lock.unlock(); 64 } 65 } 66 67 } 68 69 } 70 }
这边使用了lock,和condition来实现,它的两个方法signalAll,await相当于notifyAll,wait,效果是一样的。
=================================================================
Easier said than done.