线程打印问题

8 阅读2分钟

交替打印字符串ABC 三个线

思路:使用一个信号量,3个线程,信号量可以理解为,三个线程,初始化A信号量为1,这个时候A可以通行,b,c都会阻塞,           a获取后,然后释放许可给B,b就可以执行了,b然后执行后,释放许可给C。这样交替执行就可以了
static class Printer implements Runnable {
    private char letter;
    private Semaphore currentSemaphore;
    private Semaphore nextSemaphore;

    public Printer(char letter, Semaphore currentSemaphore, Semaphore nextSemaphore) {
        this.letter = letter;
        this.currentSemaphore = currentSemaphore;
        this.nextSemaphore = nextSemaphore;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                // 获取当前信号量的许可
                currentSemaphore.acquire();
                System.out.print(letter);
                // 释放下一个信号量的许可
                nextSemaphore.release();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
    Semaphore semaphoreA = new Semaphore(1);
    Semaphore semaphoreB = new Semaphore(0);
    Semaphore semaphoreC = new Semaphore(1);

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

交替打印1-10这10个数字

Semaphore semaphoreOdd =new Semaphore(1);
Semaphore semaphoreEven =new Semaphore(0);
Thread t1= new Thread(()->{
    for(int i=0;i<=10;i+=2){
        try {
            semaphoreOdd.acquire();
            System.out.println("odd" + i);
            semaphoreEven.release();
        }catch (Exception e){

        }
    }
});
Thread t2= new Thread(()->{
    for(int i=1;i<=10;i+=2){
        try {
            semaphoreEven.acquire();
            System.out.println("even" + i);
            semaphoreOdd.release();
        }catch (Exception e){

        }
    }
});
t1.start();
t2.start();
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
int max = 10;
int[] count = {0}; // 使用数组,主要是匿名表达式不能用普通变量。

Thread t1 = new Thread(() -> {
    while (true) {
        lock.lock();
        try {
            if (count[0] >= max) break;
            while (count[0] % 2 != 0) {
                condition1.await();
                ;
            }
            System.out.println(Thread.currentThread().getName() + count[0]++);
            condition2.signalAll();
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }

    }

},"t1");
Thread t2 = new Thread(() -> {
    while (true) {
        lock.lock();
        try {
            if (count[0] >= max) break;
            while (count[0] % 2 != 1) {
                condition2.await();
                ;
            }
            System.out.println(Thread.currentThread().getName() + count[0]++);
            condition1.signalAll();
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }

    }

},"t2");
t1.start();
t2.start();

线程交替打印1-10

写法1,基于lock condition

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AlternatePrint {
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition evenCondition = lock.newCondition(); //偶数
    private static final Condition oddCondition = lock.newCondition(); //奇数
    private static boolean evenTurn = true; // true表示该偶数线程打印

    public static void main(String[] args) {
        new Thread(() -> {
            for (int i = 0; i < 10; i += 2) {
                lock.lock();
                try {
                    while (!evenTurn) {
                        evenCondition.await(); // 等待偶数轮
                    }
                    System.out.println(Thread.currentThread().getName() + "_" + i);
                    evenTurn = false; // 轮到奇数线程
                    oddCondition.signal();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        }, "Even").start();

        new Thread(() -> {
            for (int i = 1; i < 10; i += 2) {
                lock.lock();
                try {
                    while (evenTurn) {
                        oddCondition.await(); // 等待奇数轮
                    }
                    System.out.println(Thread.currentThread().getName() + "_" + i);
                    evenTurn = true; // 轮到偶数线程
                    evenCondition.signal();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        }, "Odd").start();
    }
}

基于信号量(推荐)

Semaphore semaphore = new Semaphore(1);
Semaphore semaphore1 = new Semaphore(0);
new Thread(()->{
    for(int i=0;i<10;i+=2){
        try {
            semaphore.acquire();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"_" + i);
        semaphore1.release();
    }

},"a").start();;
new Thread(()->{
    for(int i=1;i<10;i+=2){
        try {
            semaphore1.acquire();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"_" + i);
        semaphore.release();
    }

},"b").start();;