面試題--三個執行緒迴圈列印ABC10次的幾種解決方法
阿新 • • 發佈:2019-01-04
- 使用sleep
- 使用synchronized, wait和notifyAll
- 使用Lock 和 Condition
- 使用Semaphore
- 使用AtomicInteger
下面依次給出每種解決方案的程式碼:
使用sleep
Java程式碼
- package my.thread.test;
- /**
- * @author Eric
- */
- publicclass SleepExample extends Thread {
- privatestaticint currentCount = 0;
- public SleepExample(String name) {
- this
- }
- @Override
- publicvoid run() {
- while (currentCount < 30) {
- switch (currentCount % 3) {
- case0:
- if ("A".equals(getName())) {
- printAndIncrease();
- }
- break;
- case1:
- if ("B".equals(getName())) {
- printAndIncrease();
- }
- break;
- case2:
- if ("C".equals(getName())) {
- printAndIncrease();
- }
- break;
- }
- }
- }
- privatevoid printAndIncrease() {
- print();
- increase();
- }
- privatevoid print() {
- System.out.println(getName());
- if ("C".equals(getName())) {
- System.out.println();
- }
- }
- privatevoid increase() {
- currentCount++;
- }
- publicstaticvoid main(String[] args) {
- new SleepExample("A").start();
- new SleepExample("B").start();
- new SleepExample("C").start();
- }
- }
<span style="font-family:KaiTi_GB2312;font-size:18px;">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();
}
}</span>
使用synchronized, wait和notifyAll
Java程式碼
- package my.thread.test;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- publicclass PrintThreadExample {
- publicstaticvoid 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();
- }
- privateclass LetterPrinter {
- privatechar letter = 'A';
- publicvoid print() {
- System.out.println(letter);
- if ('C' == letter) {
- System.out.println();
- }
- }
- publicvoid nextLetter() {
- switch (letter) {
- case'A':
- letter = 'B';
- break;
- case'B':
- letter = 'C';
- break;
- case'C':
- letter = 'A';
- break;
- }
- }
- /**
- * @return the letter
- */
- publicchar getLetter() {
- return letter;
- }
- }
- privateclass PrintRunnable implements Runnable {
- private LetterPrinter letterPrinter = null;
- privatechar letter = ' ';
- /**
- * @param letterPrinter
- * @param letter
- */
- public PrintRunnable(LetterPrinter letterPrinter, char letter) {
- super();
- this.letterPrinter = letterPrinter;
- this.letter = letter;
- }
- publicvoid 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();
- }
- }
- }
- }
- }
<span style="font-family:KaiTi_GB2312;font-size:18px;">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();
}
}
}
}
}</span>
JDK 1.5 引入J.U.C包之後,也給我們提供了更多實現多執行緒程式的選擇: Condition, 原子類AtomicInteger以及Semaphore等。
使用Lock 和 Condition Java程式碼
- 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
- *
- */
- publicclass ConditionExample {
- private Lock lock = new ReentrantLock();
- private Condition conditionA = lock.newCondition();
- private Condition conditionB = lock.newCondition();
- private Condition conditionC = lock.newCondition();
- /** 當前執行緒的名字 */
- privatechar currentThreadName = 'A';
- privatestaticfinal Logger logger = Logger
- .getLogger("my.thread.test.OrderPrintTest");
- publicstaticvoid 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();
- }
- privateclass ThreadA implements Runnable {
- publicvoid 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();
- }
- }
- }
- }
- privateclass ThreadB implements Runnable {
- publicvoid 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();
- }
- }
- }
- }
- privateclass ThreadC implements Runnable {
- publicvoid 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();
- }
- }
- }
- }
- }
<span style="font-family:KaiTi_GB2312;font-size:18px;">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();
}
}
}
}
}</span>
使用Semaphore
Java程式碼
- package my.thread.test;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Semaphore;
- publicclass SemaphoresExample {
- private Semaphore semaphoresA = new Semaphore(1);
- private