题目:一个线程打印 1~52,另一个线程打印字母A-Z。打印顺序为12A34B56C……5152Z。
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; /** * 一个线程打印 1~52,另一个线程打印字母A-Z。打印顺序为12A34B56C……5152Z。 * * @author Eric * */ public class ThreadCommunicationTest { private final Lock lock = new ReentrantLock(); private final Condition conditionA = lock.newCondition(); private final Condition conditionB = lock.newCondition(); private static char currentThread = ‘A‘; public static void main(String[] args) { ThreadCommunicationTest test = new ThreadCommunicationTest(); ExecutorService service = Executors.newCachedThreadPool(); service.execute(test.new RunnableA()); service.execute(test.new RunnableB()); service.shutdown(); } private class RunnableA implements Runnable { public void run() { for (int i = 1; i <= 52; i++) { lock.lock(); try { while (currentThread != ‘A‘) { try { conditionA.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(i); if (i % 2 == 0) { currentThread = ‘B‘; conditionB.signal(); } } finally { lock.unlock(); } } } } private class RunnableB implements Runnable { @Override public void run() { for (char c = ‘A‘; c <= ‘Z‘; c++) { lock.lock(); try { while (currentThread != ‘B‘) { try { conditionB.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(c); currentThread = ‘A‘; conditionA.signal(); } finally { lock.unlock(); } } } } }
上面的代码是网上找的,通过研究,学习了很多:
1.为什么是while而不是用if来判断条件,做了如下的实验
package test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 一个线程打印 1~52,另一个线程打印字母A-Z。打印顺序为12A34B56C……5152Z。 * * @author Eric * */ public class ThreadCommunicationTest { private final Lock lock = new ReentrantLock(); private final Condition conditionA = lock.newCondition(); private final Condition conditionB = lock.newCondition(); private static char currentThread = ‘A‘; public static void main(String[] args) { ThreadCommunicationTest test = new ThreadCommunicationTest(); ExecutorService service = Executors.newCachedThreadPool(); RunnableA a = test.new RunnableA(); service.execute(a); service.execute(a); RunnableB b = test.new RunnableB(); service.execute(b); service.shutdown(); } private class RunnableA implements Runnable { public void run() { for (int i = 1; i <= 100; i++) { lock.lock(); try { if (currentThread != ‘A‘) { try { conditionA.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(i + "线程名称" + Thread.currentThread().getName()); if (i % 2 == 0) { currentThread = ‘B‘; conditionB.signal(); } } finally { lock.unlock(); } } } } private class RunnableB implements Runnable { @Override public void run() { for (char c = ‘A‘; c <= ‘Z‘; c++) { lock.lock(); try { while (currentThread != ‘B‘) { try { conditionB.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(c + "线程名称" + Thread.currentThread().getName()); currentThread = ‘A‘; conditionA.signalAll(); } finally { lock.unlock(); } } } } }
开了两个线程用于执行任务A,并把判断条件改为if,则会出现如下的结果:
说明在currentThread = B的时候执行了任务A,因为当任务B调用signalAll的时候,将两个任务A线程都唤醒,假设此时任务A的一个线程输出了两个数并把currentThread条件设为了B,此时另一个任务A线程和任务B线程会同时竞争锁,如果任务A线程竞争锁成功,则会出现混乱的情况,所以要用while来进行判断
时间: 2024-12-16 02:41:53