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