三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串

using System;
using System.Threading;

class PrintThread
{
    private string text;
    private int count;
    private Semaphore semaphore;
    private Semaphore nextSemaphore;

    public PrintThread(string text, int count, Semaphore semaphore, Semaphore nextSemaphore)
    {
        this.text = text;
        this.count = count;
        this.semaphore = semaphore;
        this.nextSemaphore = nextSemaphore;
    }

    public void Run()
    {
        for (int i = 0; i < count; i++)
        {
            semaphore.WaitOne();  // 等待信号量
            Console.Write(text);
            nextSemaphore.Release();  // 释放下一个线程的信号量
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Semaphore semaphoreA = new Semaphore(1, 1);
        Semaphore semaphoreB = new Semaphore(0, 1);
        Semaphore semaphoreC = new Semaphore(0, 1);

        int n = 10;  // 打印 n 次
        PrintThread threadA = new PrintThread("A", n, semaphoreA, semaphoreB);
        PrintThread threadB = new PrintThread("B", n, semaphoreB, semaphoreC);
        PrintThread threadC = new PrintThread("C", n, semaphoreC, semaphoreA);

        Thread t1 = new Thread(threadA.Run);
        Thread t2 = new Thread(threadB.Run);
        Thread t3 = new Thread(threadC.Run);

        t1.Start();
        t2.Start();
        t3.Start();

        t1.Join();
        t2.Join();
        t3.Join();
    }
}

这段代码中,我们使用了信号量(Semaphore)来控制线程的执行顺序。在主程序中,我们创建了三个信号量semaphoreAsemaphoreBsemaphoreC,分别用于控制线程 A、B、C 的执行顺序。

然后,我们创建了三个PrintThread对象,分别表示打印 A、B、C 的线程。每个线程的构造函数中,都传入了它自己的信号量semaphore和下一个线程的信号量nextSemaphore

在每个线程的Run方法中,首先等待自己的信号量,表示它需要等待前一个线程完成打印。然后,它打印自己的字符,并释放下一个线程的信号量,表示下一个线程可以开始打印。

在主程序中,我们创建了三个Thread对象t1t2t3,分别对应线程 A、B、C,然后启动这三个线程并等待它们执行完毕。最终输出的结果是形如“ABCABCABC....”的字符串,共打印了 n 次。

public class PrintABC implements Runnable {
    private String name;
    private int count;
    private Object lock;
    private int currentCount;

    public PrintABC(String name, int count, Object lock, int currentCount) {
        this.name = name;
        this.count = count;
        this.lock = lock;
        this.currentCount = currentCount;
}
public void run() {
    while (true) {
        synchronized (lock) {
            while (currentCount % 3 != 0 && name.equals("A")) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            while (currentCount % 3 != 1 && name.equals("B")) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            while (currentCount % 3 != 2 && name.equals("C")) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if (currentCount >= count * 3) {
                break;
            }

            System.out.print(name);
            currentCount++;

            lock.notifyAll();
        }
    }
}

public static void main(String[] args) {
    int count = 5;
    Object lock = new Object();
    new Thread(new PrintABC("A", count, lock, 0)).start();
    new Thread(new PrintABC("B", count, lock, 1)).start();
    new Thread(new PrintABC("C", count, lock, 2)).start();
}
View Code


在这段代码中,我们创建了一个`PrintABC`类来表示每个线程。构造函数接收线程的名称、计数值、锁对象和当前计数器的值。在`run()`方法中,我们使用`synchronized`关键字来确保线程之间的同步。线程会循环打印字母,并根据当前计数器的值判断该线程是否需要打印字母。在每次打印完字母后,线程会通知所有等待该锁的线程继续执行,以便下一个线程打印字母。如果计数器超过了给定的计数值,则线程会退出循环。

在主程序中,我们创建了一个锁对象和三个`PrintABC`对象,分别代表线程 A、B、C。然后,我们启动每个线程,并传递当前计数器的值,以便线程可以判断是否需要打印字母。每个线程在打印完字母后,会通知下一个线程继续执行,直到所有线程完成任务并退出。最终,输出的字符串形如“ABCABCABC...”。

posted @ 2023-03-29 23:40  elegydance  阅读(153)  评论(0编辑  收藏  举报