有三個線程分別打印A、B、C, 請用多線程編程實現,在屏幕上循環打印10次ABCABC… java
這是一個比較經常使用的關於線程的考題,通常出如今應屆生的校園招聘試卷上。編程
本文給出以下四種解決方法:多線程
/** * @author wangmengjun * */ public class SyncObj { private char letter = 'A'; public void nextLetter() { switch (letter) { case 'A': letter = 'B'; break; case 'B': letter = 'C'; break; case 'C': letter = 'A'; break; default: break; } } public char getLetter() { return letter; } }
/** * @author wangmengjun * */ public class PrintLetterRunnable implements Runnable { private SyncObj syncObj; private char letter; public PrintLetterRunnable(SyncObj syncObj, char letter) { this.syncObj = syncObj; this.letter = letter; } public void run() { for (int i = 0; i < 10; i++) { synchronized (syncObj) { /** * 若是當前線程的字符和同步對象的字符不一致,則當前線程一直等待 */ while (letter != syncObj.getLetter()) { try { syncObj.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 輸出當前線程的字符 */ System.out.print(letter); /** * 改變同步對象的letter值 */ syncObj.nextLetter(); /** * 通知其它全部等待線程 */ syncObj.notifyAll(); } } } }
public class Main { public static void main(String[] args) { SyncObj syncObj = new SyncObj(); Thread threadA = new Thread(new PrintLetterRunnable(syncObj, 'A')); Thread threadB = new Thread(new PrintLetterRunnable(syncObj, 'B')); Thread threadC = new Thread(new PrintLetterRunnable(syncObj, 'C')); threadA.start(); threadB.start(); threadC.start(); } }
ABCABCABCABCABCABCABCABCABCABC
JDK 1.5 引入J.U.C包以後,也給咱們提供了更多實現多線程程序的選擇: Condition, 原子類AtomicInteger以及Semaphore等。 ui
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; 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'; 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) { e.printStackTrace(); } } System.out.print("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) { e.printStackTrace(); } } /** * 打印信息B */ System.out.print("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) { e.printStackTrace(); } } /** * 打印信息C */ System.out.print("C"); /** * 將當前線程值置爲A 並經過ThreadA來執行 */ currentThreadName = 'A'; conditionA.signal(); } finally { lock.unlock(); } } } } }
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) { e.printStackTrace(); } System.out.print("A"); semaphoresB.release(); } } } private class RunnableB implements Runnable { public void run() { for (int i = 0; i < 10; i++) { try { semaphoresB.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("B"); semaphoresC.release(); } } } private class RunnableC implements Runnable { public void run() { for (int i = 0; i < 10; i++) { try { semaphoresC.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("C"); semaphoresA.release(); } } } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerExample { private AtomicInteger sycValue = new AtomicInteger(0); private static final int MAX_SYC_VALUE = 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.print("A"); sycValue.getAndIncrement(); } } } } private class RunnableB implements Runnable { public void run() { while (sycValue.get() < MAX_SYC_VALUE) { if (sycValue.get() % 3 == 1) { System.out.print("B"); sycValue.getAndIncrement(); } } } } private class RunnableC implements Runnable { public void run() { while (sycValue.get() < MAX_SYC_VALUE) { if (sycValue.get() % 3 == 2) { System.out.print("C"); sycValue.getAndIncrement(); } } } } }
有三個線程分別打印A、B、C, 請用多線程編程實現,在屏幕上循環打印10次ABCABC… this
如上題目解答的方法有多種,本文只給出了幾種比較經常使用的解法。atom
掌握本文提供的幾個方法,那麼,相似的題目按照這個思路,也是能夠解決的。spa
如:線程
一個線程打印 1~52,另外一個線程打印字母A-Z。打印順序爲12A34B56C……5152Z。 code
再如:對象
有四個線程一、二、三、4。線程1的功能就是輸出A,線程2的功能就是輸出B,以此類推......... 如今有四個文件file1,file2,file3, file4。初始都爲空。
現要讓四個文件呈以下格式: file1:A B C D A B.... file2:B C D A B C.... file3:C D A B C D.... file4:D A B C D A....
這些題目都是類似相通的,有興趣的朋友能夠本身編寫一下試試。