Java线程交替打印问题

119 阅读2分钟

线程交替打印ABC,分别打印10次。

semaphore 实现

  • 思路:信号量的逻辑。信号量大于0,才能拿到凭证去执行。小于等于0调用acquire都会阻塞,直至信号量大于0。 3个信号量。一个初始化为1。另外2个为0。由于另外2个都为0,所以获取凭证都会阻塞,a先执行,执行后,b的信号量为1。然后b就可以执行打印,b执行后,b的信号为0,c可以拿到凭证,c的信号量为1。
    // 信号量 A,初始许可为 1,允许 A 先打印
    private static Semaphore semaphoreA = new Semaphore(1);
    // 信号量 B,初始许可为 0,B 等待 A 打印后才能打印
    private static Semaphore semaphoreB = new Semaphore(0);
    // 信号量 C,初始许可为 0,C 等待 B 打印后才能打印
    private static Semaphore semaphoreC = new Semaphore(0);
    


    static class Printer implements Runnable{
        private String letter;
        private Semaphore currentSemaphore;
        private Semaphore nextSemaphore;
        public Printer(String letter, Semaphore currentSemaphore, Semaphore nextSemaphore) {
            this.letter = letter;
            this.currentSemaphore = currentSemaphore;
            this.nextSemaphore = nextSemaphore;
        }
        public void run() {
            for(int i=0;i<10;i++){
                try {
                    currentSemaphore.acquire();
                    System.out.println(letter);
                    nextSemaphore.release();
                }catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
            }
        }

    }





public static void main(String[] args) {


    Thread threadA = new Thread(new Printer("A", semaphoreA, semaphoreB));
    Thread threadB = new Thread(new Printer("B", semaphoreB, semaphoreC));
    Thread threadC = new Thread(new Printer("C", semaphoreC, semaphoreA));
    threadA.start();
    threadB.start();
    threadC.start();
    
        };

使用Conditon来实现

  • 核心 3个conditon,来进行切换
private static final Lock lock = new ReentrantLock();
private static final Condition conditionA = lock.newCondition();
private static final Condition conditionB = lock.newCondition();
private static final Condition conditionC = lock.newCondition();
private static int state = 0; // 0: print A, 1: print B, 2: print C

public static void main(String[] args) {
    Thread threadA = new Thread(new PrintTask('A', 0, conditionA, conditionB));
    Thread threadB = new Thread(new PrintTask('B', 1, conditionB, conditionC));
    Thread threadC = new Thread(new PrintTask('C', 2, conditionC, conditionA));

    threadA.start();
    threadB.start();
    threadC.start();
}

static class PrintTask implements Runnable {
    private final char ch;
    private final int targetState;
    private final Condition currentCond;
    private final Condition nextCond;

    public PrintTask(char ch, int targetState, Condition currentCond, Condition nextCond) {
        this.ch = ch;
        this.targetState = targetState;
        this.currentCond = currentCond;
        this.nextCond = nextCond;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            lock.lock();
            try {
                while (state != targetState) {
                    currentCond.await();
                }
                System.out.print(ch);
                state = (state + 1) % 3;
                nextCond.signal();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // restore interrupted status
            } finally {
                lock.unlock();
            }
        }
    }
}

实现一个简单的生产者,消费者

import com.sun.tools.javac.Main;

import javax.swing.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main2 {
    private int max=10;
    private int min=1;
    private int number=0;
    private ReentrantLock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();
    void produce(){
        try {
            lock.lock();
            while (number>=max){
                condition.await();
            }
            number++;
            System.out.println("producer produce_" + number);
            condition.signalAll();
        }catch (Exception e){

        }finally {
            lock.unlock();
        }
    }
    void consume(){
        try {
            lock.lock();
            while(number<min){
                condition.await();
            }
            number--;
            System.out.println("consume" + number);
            condition.signalAll();
        }catch (Exception e){

        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        Main2 main2 = new Main2();
        new Thread(()->{
            for(int i=0;i<10;i++){
                main2.produce();
            }
        }).start();//生产者
        //消费者
        new Thread(()->{
            for (int i=1;i<=10;i++){
                main2.consume();
            }
        },String.valueOf("消费者")).start();


    }



}