大概的问题是这样的:
有A,B,C三个线程, A线程输出A, B线程输出B, C线程输出C
要求, 同时启动三个线程, 按顺序输出ABC, 循环10次
这是一个多线程协同的问题, 本身多线程是没有执行顺序的, 顺序不一定, Java在concurrent里面提供了多线程同步的支持
使用ReentrantLock来解决, 还有个state整数用来判断轮到谁执行了
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ABC { private static Lock lock = new ReentrantLock();//通过JDK5中的锁来保证线程的访问的互斥 private static int state = 0; static class ThreadA extends Thread { @Override public void run() { for (int i = 0; i < 10;) { lock.lock(); if (state % 3 == 0) { System.out.print("A"); state++; i++; } lock.unlock(); } } } static class ThreadB extends Thread { @Override public void run() { for (int i = 0; i < 10;) { lock.lock(); if (state % 3 == 1) { System.out.print("B"); state++; i++; } lock.unlock(); } } } static class ThreadC extends Thread { @Override public void run() { for (int i = 0; i < 10;) { lock.lock(); if (state % 3 == 2) { System.out.print("C"); state++; i++; } lock.unlock(); } } } public static void main(String[] args) { new ThreadA().start(); new ThreadB().start(); new ThreadC().start(); } }
使用lock来保证只有一个线程在输出操作, 要保证了state不会被两个线程同时修改, 思路简单
还可以使用condition, condition的效率可能会更高一些, await会释放lock锁, condition的await和signal与object的wait和notify方法作用类似
package moreThread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** */ public class ABC2 { private static Lock lock = new ReentrantLock(); private static int count = 0; private static Condition A = lock.newCondition(); private static Condition B = lock.newCondition(); private static Condition C = lock.newCondition(); static class ThreadA extends Thread { @Override public void run() { lock.lock(); try { for (int i = 0; i < 10; i++) { while (count % 3 != 0) { A.await(); // 会释放lock锁 System.out.print("A"); count++; B.signal(); // 唤醒相应线程 } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } static class ThreadB extends Thread { @Override public void run() { lock.lock(); try { for (int i = 0; i < 10; i++) { while (count % 3 != 0) { B.await(); // 会释放lock锁 System.out.print("B"); count++; C.signal(); // 唤醒相应线程 } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } static class ThreadC extends Thread { @Override public void run() { lock.lock(); try { for (int i = 0; i < 10; i++) { while (count % 3 != 0) { C.await(); // 会释放lock锁 System.out.print("C"); count++; A.signal(); // 唤醒相应线程 } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public static void main(String[] args) throws InterruptedException { new ThreadA().start(); new ThreadB().start(); ThreadC threadC = new ThreadC(); threadC.start(); threadC.join(); System.out.println(count); } }
使用信号量也可以, 这个思路最简单, 整个代码也比较简洁
import java.util.concurrent.Semaphore; public class ABC3 { private static Semaphore A = new Semaphore(1); private static Semaphore B = new Semaphore(1); private static Semaphore C = new Semaphore(1); static class ThreadA extends Thread { @Override public void run() { try { for (int i = 0; i < 10; i++) { A.acquire(); System.out.print("A"); B.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadB extends Thread { @Override public void run() { try { for (int i = 0; i < 10; i++) { B.acquire(); System.out.print("B"); C.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadC extends Thread { @Override public void run() { try { for (int i = 0; i < 10; i++) { C.acquire(); System.out.println("C"); A.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { B.acquire(); C.acquire(); // 开始只有A可以获取, BC都不可以获取, 保证了A最先执行 new ThreadA().start(); new ThreadB().start(); new ThreadC().start(); } }
注意:
lock是需要lock所有者去释放的, 即谁lock, 谁释放, 不可以跨线程, 会报java.lang.IllegalMonitorStateException;
semaphore是没有所有者的说法, 可以跨线程释放和获取.