Java实现多线程交替打印ABC
实现java通4个线程顺序打印ABC四个字母,第一个线程打印A,第二个线程打印B,第三个线程打印C,每个线程打印10次
基于synchronized+wait/notify
public class printABC {
private volatile static int state = 0;
private static final Object lock = new Object();
public static void main(String[] args) {
Thread A = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
synchronized (lock){
while (state%3!=0){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
state++;
lock.notifyAll();
}
}
}
});
Thread B = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
synchronized(lock){
while (state%3!=1){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
state++;
lock.notifyAll();
}
}
}
});
Thread C = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
synchronized(lock){
while (state%3!=2){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
state++;
lock.notifyAll();
}
}
}
});
A.start();
B.start();
C.start();
}
}
基于ReentrantLock+Condition
实现方式如下,可以看到核心方法为将wait和notifyAll转换为await和signal,好处是可以做特定线程的唤醒。最后因为增加的是reetrantLock锁,所以要在finally代码块中对lock对象进行解锁
public class MultiConditionPrintABC {
private static Lock lock = new ReentrantLock();
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();
private static Condition conditionC = lock.newCondition();
private static int state = 0;
static class ThreadA implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (state % 3 != 0) {
conditionA.await();
}
System.out.print("A");
state++;
conditionB.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
static class ThreadB implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (state % 3 != 1) {
conditionB.await();
}
System.out.print("B");
state++;
conditionC.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
static class ThreadC implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (state % 3 != 2) {
conditionC.await();
}
System.out.print("C");
state++;
conditionA.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) {
new Thread(new ThreadA()).start();
new Thread(new ThreadB()).start();
new Thread(new ThreadC()).start();
}
}
使用Semaphore机制
Semaphore又称信号量,是操作系统中的一个概念,在Java并发编程中,信号量控制的是线程并发的数量。
public Semaphore(int permits)
其中参数permits就是允许同时运行的线程数目;
Semaphore是用来保护一个或者多个共享资源的访问,Semaphore内部维护了一个计数器,其值为可以访问的共享资源的个数。一个线程要访问共享资源,先获得信号量,如果信号量的计数器值大于1,意味着有共享资源可以访问,则使其计数器值减去1,再访问共享资源。如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之前进入休眠的线程将被唤醒并再次试图获得信号量。
import java.util.concurrent.Semaphore;
public class SemaphorePrint {
// 以A开始的信号量,初始信号量数量为1
private static Semaphore A = new Semaphore(1);
// B、C信号量,A完成后开始,初始信号数量为0
private static Semaphore B = new Semaphore(0);
private static Semaphore C = new Semaphore(0);
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
try {
A.acquire();// A获取信号执行,A信号量减1,当A为0时将无法继续获得该信号量
System.out.print("A");
B.release();// B释放信号,B信号量加1(初始为0),此时可以获取B信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
try {
B.acquire();
System.out.print("B");
C.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
try {
C.acquire();
System.out.print("C");
A.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread1.start();
thread2.start();
thread3.start();
}
}