三个线程交替打印ABC
前言
我想到的可以用三种办法来解决,分别是信号量,Synchronized以及ReentrantLock。
信号量方法
设置三个信号量,分别标记三个临界区资源的状态即可,这种方法最简单明了,是乐观锁的一种用法。
/**
* 使用信号量
*/
public class PrintTask3 {
static Semaphore one=new Semaphore(0);
static Semaphore two=new Semaphore(0);
static Semaphore three=new Semaphore(1);
public static void main(String[] args) {
PrintA printA=new PrintA();
PrintB printB=new PrintB();
PrintC printC=new PrintC();
printA.start();
printB.start();
printC.start();
}
static class PrintA extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
three.acquire(); // 需要第三个
System.out.print("A");
one.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
static class PrintB extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try{
one.acquire();
System.out.print("B");
two.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
static class PrintC extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
two.acquire();
System.out.print("C");
three.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
Synchronized锁
用三个boolean变量来标识三个线程的运行状态,通过synchronized对一个公共对象加锁来进行同步操作。
/**
* 使用synchronized
*/
public class PrintTask {
static volatile boolean one=false;
static volatile boolean two=false;
static volatile boolean three=true;
static final Object lock=new Object();
public static void main(String[] args) {
PrintA printA=new PrintA();
PrintB printB=new PrintB();
PrintC printC=new PrintC();
printA.start();
printB.start();
printC.start();
}
static class PrintA extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
synchronized (lock){
while(!three){
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
three=false;
System.out.print("A");
one=true;
lock.notifyAll();
}
}
}
}
static class PrintB extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
synchronized (lock){
while(!one){
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
one=false;
System.out.print("B");
two=true;
lock.notifyAll();
}
}
}
}
static class PrintC extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
synchronized (lock){
while(!two){
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
two=false;
System.out.print("C");
three=true;
lock.notifyAll();
}
}
}
}
}
ReentrantLock加锁
与synchronized方法差不多,不同的是,synchronized通过对象本身自带的wait()和signal()方法进行线程间通信,而ReentrantLock需要通过使用Condition进行线程间通信。
/**
* 使用ReentrantLock
*/
public class PrintTask2 {
static Condition[] conditions;
static boolean oneDown = false;
static boolean twoDown = false;
static boolean threeDown = true;
static ReentrantLock lock = new ReentrantLock(); // 一把锁来标记共享资源
public static void main(String[] args) {
conditions=new Condition[3];
for (int i = 0; i < 3; i++) {
conditions[i] = lock.newCondition();
}
PrintA printA=new PrintA();
PrintB printB=new PrintB();
PrintC printC=new PrintC();
printA.start();
printB.start();
printC.start();
}
static class PrintA extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (!threeDown) {
conditions[0].await();
}
System.out.print("A");
threeDown = false;
oneDown = true;
conditions[1].signal(); // 唤醒下一
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}
}
static class PrintB extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (!oneDown) {
conditions[1].await();
}
System.out.print("B");
twoDown=true;
oneDown=false;
conditions[2].signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
lock.unlock();
}
}
}
}
static class PrintC extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (!twoDown) {
conditions[2].await();
}
System.out.print("C");
twoDown=false;
threeDown= true;
conditions[0].signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
lock.unlock();
}
}
}
}
}
结束语
好久没写,又忘了怎么写了,记录一下~。