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

最近发现公司有份笔试试卷中有道多线程的[b]题目[/b]:[color=blue][b]有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…[/b][/color]

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

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

[list]
[*][b]使用sleep
[*]使用synchronized, wait和notifyAll
[*]使用Lock 和 Condition
[*]使用Semaphore
[*]使用AtomicInteger[/b]
[/list]

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

[color=blue][u][b]使用sleep[/b][/u][/color]

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();
}

}



[color=blue][u][b]使用synchronized, wait和notifyAll[/b][/u][/color]

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();

}
}

}

}

}



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

[color=blue][u][b]
使用Lock 和 Condition[/b][/u][/color]
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();
}

}
}
}
}




[color=blue][u][b]使用Semaphore[/b][/u][/color]
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();
}
}
}
}



[color=blue]
[u][b]使用AtomicInteger[/b][/u][/color]
package my.thread.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerExample {

private AtomicInteger sycValue = https://www.it610.com/article/new AtomicInteger(0);

private static final int MAX_SYC_VALUE = https://www.it610.com/article/3 * 10;

public static void main(String[] args) {
AtomicIntegerExample example = new AtomicIntegerExample();
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() {

while (sycValue.get() < MAX_SYC_VALUE) {
if (sycValue.get() % 3 == 0) {
System.out.println(String.format("第%d遍",
sycValue.get() / 3 + 1));
System.out.println("A");
sycValue.getAndIncrement();
}
}

}
}

private class RunnableB implements Runnable {

public void run() {

while (sycValue.get() < MAX_SYC_VALUE) {
if (sycValue.get() % 3 == 1) {
System.out.println("B");
sycValue.getAndIncrement();
}
}

}
}

private class RunnableC implements Runnable {

public void run() {

while (sycValue.get() < MAX_SYC_VALUE) {
if (sycValue.get() % 3 == 2) {
System.out.println("C");
System.out.println();
sycValue.getAndIncrement();
}
}

}
}
}



转载请注明出处[url]http://mouselearnjava.iteye.com/blog/1949228[/url]

    推荐阅读