What

之前同事遇到过这样一个面试题,大概是用三个线程顺序打印ABC字符串,打印10遍。请给出至少一种解决方案。

Why

面试官为什么出这个问题呢?我想大概主要是想考验一下面试者多线程的熟悉度,理解和运用。

How

我想了一会儿,给出大概3种实现方案。一种使用synchronized关键字来做锁,另外两种不使用锁机制,大同小异的实现。
Talk is cheap,show me your code!!!

  • 实现一,使用synchronized关键字来做锁。
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;

    /**
    * 三个线程顺序打印字符串ABC,打印10遍
    * 写法一
    * */
    public class ThreadTest {
    private boolean flagA =true;
    private boolean flagB =false;
    private boolean flagC =false;
    private Object objA = new Object();
    private Object objB = new Object();
    private Object objC = new Object();
    private void printA() throws InterruptedException{
    for(int i=0;i<10;i++){
    synchronized(objA){
    synchronized(objB){
    while(flagA){
    System.out.println("A");
    flagA=false;
    flagB=true;
    objB.notify();
    }
    }
    objA.wait();
    }
    }
    }
    private void printB() throws InterruptedException{
    for(int i=0;i<10;i++){
    synchronized(objB){
    synchronized(objC){
    while(flagB){
    System.out.println("B");
    flagB=false;
    flagC=true;
    objC.notify();
    }
    }
    objB.wait();
    }
    }
    }

    private void printC() throws InterruptedException{
    for(int i=0;i<10;i++){
    synchronized(objC){
    synchronized(objA){
    while(flagC){
    System.out.println("C");
    flagA=true;
    flagC=false;
    objA.notify();
    }
    }
    objC.wait();
    }
    }
    }
    public static void main(String[] args) throws InterruptedException {
    final ThreadTest ThreadTest =new ThreadTest();

    Runnable ra = new Runnable(){
    public void run(){
    try {
    ThreadTest.printA();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    };
    Runnable rb = new Runnable(){
    public void run(){
    try {
    ThreadTest.printB();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    };
    Runnable rc = new Runnable(){
    public void run(){
    try {
    ThreadTest.printC();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    };
    new Thread(ra).start();
    Thread.sleep(300);
    new Thread(rb).start();
    Thread.sleep(300);
    new Thread(rc).start();

    }


    }

  • 实现二
    import java.util.concurrent.atomic.AtomicInteger;
    /**
    * 三个线程顺序打印字符串ABC,打印10遍
    * 写法二
    * @author lichaoqiang
    * */
    public class ThreadTest2 implements Runnable{


    static Thread[] threads = new Thread[3];
    static int len = 3;
    static final AtomicInteger ai = new AtomicInteger(1);
    String val="";

    public ThreadTest2(String val){
    this.val = val;
    }

    public void run() {
    while(true){
    if(ai.get()<= 30){

    if("A".equals(val)){

    if(ai.get()%len == 1){
    // TODO Auto-generated method stub
    System.out.println(Thread.currentThread().getName()+val);
    ai.getAndIncrement();
    }
    }
    if("B".equals(val)){
    if(ai.get()%len == 2){
    // TODO Auto-generated method stub
    System.out.println(Thread.currentThread().getName()+val);
    ai.getAndIncrement();
    }
    }
    if("C".equals(val)){
    if(ai.get()%len == 0){
    // TODO Auto-generated method stub
    System.out.println(Thread.currentThread().getName()+val);
    ai.getAndIncrement();
    }
    }
    }else{
    break;
    }

    }

    //
    }

    public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub


    threads[0] = new Thread(new ThreadTest2("A"));

    threads[1] = new Thread(new ThreadTest2("B"));

    threads[2] = new Thread(new ThreadTest2("C"));

    threads[0].start();
    threads[1].start();
    threads[2].start();
    }

    }
  • 实现三

    package com.licq.thread;

    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    /**
    * 三个线程顺序打印字符串ABC,打印10遍
    * 写法三
    * */
    public class ThreadTest3 {

    private static int seq = 0;
    private static Thread[] threads = new Thread[3];
    private static Map<String, String> mapping = new HashMap<String, String>();

    public static void main(String[] args) {
    mapping.put("0", "A");
    mapping.put("1", "B");
    mapping.put("2", "C");

    for (int i = 0; i < threads.length; i++) {
    threads[i] = new Thread(new Runnable() {

    public void run() {
    while (true) {
    if(seq >= 30){
    break;
    }
    String threadName = Thread.currentThread().getName();
    if (seq % threads.length == Integer
    .parseInt(threadName)) {
    System.out.println("------------" + mapping.get(threadName) + "-----------");
    seq = seq + 1;
    } else {
    try {
    TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
    }
    }
    }
    }
    });
    threads[i].setName(String.valueOf(i));
    threads[i].start();
    }

    }


    }

SUMMARY

以上三种是比较简单的实现方式,当然还有其他很多实现方式,欢迎有更简单更优雅的实现方式贴在下面一起交流。