Bootstrap

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();
    }

}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;