线程理解:三个线程交替顺序打印ABC

一、题目描述

建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印
这里参照网上方案,特此整理如下:
1、使用synchronized, wait和notifyAll
2、使用Lock->ReentrantLock 和 state标志
3、使用Lock->ReentrantLock 和Condition(await 、signal、signalAll)
4、使用AtomicInteger

二、synchronized,wait和notifyAll方式

/**
 * @author 60055558
 * @version 1.0
 */
public class ThreadPrinter01 {
    /*使用同步代码块synchronized、wait、notifyAll控制线程执行顺序
    */
    public static void main(String[] args)  throws Exception{
        Object a = new Object();
        Object b = new Object();
        Object c = new Object();
        ThreadPrinter pa = new ThreadPrinter("A",c,a);
        ThreadPrinter pb = new ThreadPrinter("B",a,b);
        ThreadPrinter pc = new ThreadPrinter("C",b,c);

        new Thread(pa).start();
        Thread.sleep(10);// 保证初始ABC的启动顺序
        new Thread(pb).start();
        Thread.sleep(10);
        new Thread(pc).start();
        Thread.sleep(10);
    }

    public static class ThreadPrinter implements Runnable{
        private String name;//线程名称
        private Object prev;//前一个线程
        private Object self;//当前线程

        private ThreadPrinter(String name,Object prev,Object self){
            this.name = name;
            this.prev = prev;
            this.self = self;
        }

        public void run() {
            int count = 9;
            while (count > 0){ //多线程并发,不能用if,必须使用while循环
                synchronized (prev){ //先获取prev锁
                    synchronized (self){ //再获取self锁
                        System.out.print(name);
                        count --;
                        self.notifyAll(); //self锁执行完,唤醒其他线程竞争self锁,,注意此时self锁并未立即释放。
                                          //notifyAll()方法(唤醒所有 wait 线程)
                                          //notify()方法(只随机唤醒一个 wait 线程)
                    }
                    // 此时执行完self的同步块,这时self锁才释放。
                    try{
                       if(count == 0){ //代表最后一次打印,则唤醒所有prev进程,释放prev对象锁
                           prev.notifyAll();
                       } else{
                           prev.wait(); // 立即释放 prev锁,当前线程休眠,等待唤醒
                       }
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                }
            }
        }
    }

}

三、Lock->ReentrantLock 和 state标志

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

/**
 * @author 60055558
 * @version 1.0
 */
public class ThreadPrinter02 {
    private static Lock lock = new ReentrantLock();
    private static int state = 0;//通过state的值来确定是哪个线程打印
    public static void main(String[] args) {
        new ThreadA().start();
        new ThreadB().start();
        new ThreadC().start();
    }

    //public static class ThreadPrinter implements Runnable{}
    public static  class ThreadA extends Thread {
       public void run(){
           for (int i=0;i<10;){
               try{
                   lock.lock();
                   while (state%3 == 0){// 多线程并发,不能用if,必须用循环测试等待条件,避免虚假唤醒
                       System.out.print("A");
                       state ++;
                       i ++ ;
                   }
               }finally{
                   lock.unlock();
               }
           }
       }
    }

    public static  class ThreadB extends Thread {
        public void run(){
            for (int i=0;i<10;){
                try{
                    lock.lock();
                    while (state%3 == 1){
                        System.out.print("B");
                        state ++;
                        i ++ ;
                    }
                }finally{
                    lock.unlock();
                }
            }
        }
    }

    public static  class ThreadC extends Thread {
        public void run(){
            for (int i=0;i<10;){
                try{
                    lock.lock();
                    while (state%3 == 2){
                        System.out.print("C");
                        state ++;
                        i ++ ;
                    }
                }finally{
                    lock.unlock();
                }
            }
        }
    }
}

四、Lock->ReentrantLock 和Condition

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

/**
 * @author 60055558
 * @version 1.0
 */
public class ThreadPrinter03 {
    private static Lock lock = new ReentrantLock();
    private static Condition A = lock.newCondition();//Condition是被绑定到Lock上的,必须使用lock.newCondition()才能创建一个Condition
    private static Condition B = lock.newCondition();
    private static Condition C = lock.newCondition();

    private static int count = 0;

    public static void main(String[] args) {
        new ThreadPrintA().start();
        new ThreadPrintB().start();
        new ThreadPrintC().start();
    }

    public static class ThreadPrintA extends Thread{
        public void run(){
            try{
                lock.lock();
                for(int i=0;i<10;i++){
                    while (count % 3 != 0){//注意这里是不等于0,也就是说没轮到该线程执行,之前一直等待状态
                       A.await();//该线程A将会释放lock锁,构造成节点加入等待队列并进入等待状态
                    }
                    System.out.print("A");
                    count++;
                    B.signalAll();// A执行完唤醒B线程
                }

            }catch(Exception e){
                e.printStackTrace();
            }finally{
                lock.unlock();
            }
        }
    }

    public static class ThreadPrintB extends Thread{
        public void run(){
            try{
                lock.lock();
                for(int i=0;i<10;i++){
                    while(count % 3 != 1){
                        B.await();// B释放lock锁,当前面A线程执行后会通过B.signalAll()唤醒该线程
                    }
                    System.out.print("B");
                    count ++;
                    C.signalAll();// B执行完唤醒C线程
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally{
                lock.unlock();
            }
        }
    }

    public static class ThreadPrintC extends Thread{
        public void run(){
            try{
                lock.lock();
                for(int i=0;i<10;i++){
                    while(count % 3 != 2){
                        C.await();// C释放lock锁
                    }
                    System.out.print("C");
                    count ++;
                    A.signalAll();// C执行完唤醒A线程
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
}

五、AtomicInteger

import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 60055558
 * @version 1.0
 */
public class ThreadPrinter04 {
    private AtomicInteger ai = new AtomicInteger(0);
    private static final int MAX_SYC_VALUE = 9;

    public static void main(String[] args) {
        ThreadPrinter04 print = new ThreadPrinter04();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 4, 5, TimeUnit.MILLISECONDS, new SynchronousQueue());
        executor.execute(print.new ThreadPrintA());
        executor.execute(print.new ThreadPrintB());
        executor.execute(print.new ThreadPrintC());
        executor.shutdown();
    }

    private class ThreadPrintA implements Runnable{
        public void run() {
            while (ai.get() < MAX_SYC_VALUE){
                if(ai.get() % 3 == 0){
                    System.out.print("A");
                    ai.getAndIncrement();
                }
            }
        }
    }

    private class ThreadPrintB implements Runnable{
        public void run() {
            while (ai.get() < MAX_SYC_VALUE){
                if(ai.get() % 3 == 1){
                    System.out.print("B");
                    ai.getAndIncrement();
                }
            }
        }
    }

    private class ThreadPrintC implements Runnable{
        public void run() {
            while (ai.get() < MAX_SYC_VALUE){
                if(ai.get() % 3 == 2){
                    System.out.print("C");
                    ai.getAndIncrement();
                }
            }
        }
    }
}

参考文章
https://blog.csdn.net/hefenglian/article/details/82596072

你可以使用多线程编程来实现三个线程交替打印abc。下面是一个示例代码: ```python import threading class PrintABC: def __init__(self): self.current_letter = 'A' self.lock = threading.Lock() def print_a(self): for _ in range(10): with self.lock: while self.current_letter != 'A': self.lock.wait() print('A', end='') self.current_letter = 'B' self.lock.notify_all() def print_b(self): for _ in range(10): with self.lock: while self.current_letter != 'B': self.lock.wait() print('B', end='') self.current_letter = 'C' self.lock.notify_all() def print_c(self): for _ in range(10): with self.lock: while self.current_letter != 'C': self.lock.wait() print('C', end='') self.current_letter = 'A' self.lock.notify_all() def main(): printer = PrintABC() thread_a = threading.Thread(target=printer.print_a) thread_b = threading.Thread(target=printer.print_b) thread_c = threading.Thread(target=printer.print_c) thread_a.start() thread_b.start() thread_c.start() thread_a.join() thread_b.join() thread_c.join() if __name__ == '__main__': main() ``` 这个例子中,我们创建了一个 `PrintABC` 类,其中包含了三个方法 `print_a`、`print_b` 和 `print_c` 分别用于打印字母 'A'、'B' 和 'C'。在每个方法中,使用 `with self.lock` 来获取锁对象并进入临界区域。通过 `self.current_letter` 来确定当前应该打印的字母,并使用 `while self.current_letter != 'A'` 等待其他线程改变 `self.current_letter` 的值。当当前字母符合要求时,打印字母并切换到下一个字母,然后使用 `self.lock.notify_all()` 唤醒其他等待的线程。 在 `main` 方法中,我们创建了三个线程并分别启动它们,然后使用 `join` 方法等待所有线程执行完毕。运行这段代码时,你将会看到三个线程交替打印字母 'A'、'B' 和 'C',每个字母连续打印十次。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值