题目:一个线程打印 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来进行判断