3个线程,分别打印A,B,C,循环打印ABC十次

多线程打印ABC
本文介绍了一个使用Java多线程实现循环打印ABC字符的应用案例。通过三个线程分别控制打印A、B、C字符,并利用synchronized关键字和wait/notify机制确保了线程间的有序执行。文章展示了如何通过共享对象来协调线程执行顺序,最终实现按顺序循环打印ABC十次。
package test.thread;

/**3个线程,分别打印A,B,C,循环打印ABC十次
 * @author lsh
 *
 */
public class TestABC {

	public static void main(String[] args) throws Exception {
		ABC abc = new ABC();	//多线程中用来锁住对象 操作,已实现同步功能
		A a = new A(abc);
		B b = new B(abc);
		C c = new C(abc);
		Thread tA = new Thread(a);
		Thread tB = new Thread(b);
		Thread tC = new Thread(c);
		tC.start();
		tB.start();
		tA.start();
		tA.join();	//等待线程完成
		tB.join();
		tC.join();
		System.out.println("完成");
	}
}

class ABC {
	int i = 1;	//打印ABC的标志,1打印A,2打印B,3打印C
}

/**	线程A 打印 字符A
 * @author lsh
 *
 */
class A implements Runnable {
	ABC abc;

	public A(ABC abc) {
		this.abc = abc;
	}

	private void prin() {
		synchronized (abc) {
			try {
				for (int i = 0; i < 10; i++) {
					while (abc.i != 1) {
						abc.wait();	//等待
					}
					System.out.print("A");
					abc.i = 2;
					abc.notifyAll();//释放对象锁
				}

			} catch (Exception e) {
				e.printStackTrace();
				abc.notifyAll();
			}
		}
	}

	@Override
	public void run() {
		prin();
	}

}

/**	线程B 打印 字符B
 * @author lsh
 *
 */
class B implements Runnable {
	ABC abc;

	public B(ABC abc) {
		this.abc = abc;
	}

	private void prin() {
		synchronized (abc) {
			try {
				for (int i = 0; i < 10; i++) {
					while (abc.i != 2) {
						abc.wait();
					}
					System.out.print("b");
					abc.i = 3;
					abc.notifyAll();
				}
			} catch (Exception e) {
				e.printStackTrace();
				abc.notifyAll();
			}
		}
	}

	@Override
	public void run() {
		prin();
	}

}

/**	线程C 打印 字符C
 * @author lsh
 *
 */
class C implements Runnable {
	ABC abc;

	public C(ABC abc) {
		this.abc = abc;
	}

	private void prin() {
		synchronized (abc) {
			try {
				for (int i = 0; i < 10; i++) {
					while (abc.i != 3) {
						abc.wait();
					}
					System.out.println("c"+"   "+(i+1)+"次");
					abc.i = 1;
					abc.notifyAll();
				}
			} catch (Exception e) {
				e.printStackTrace();
				abc.notifyAll();
			}
		}
	}

	@Override
	public void run() {
		prin();
	}

}

<think>好的,我需要帮助用户实现一个多线程程序,让三个线程按顺序打印A、B、C各10次,严格保持ABC的顺序。用户之前已经提供了一些参考资料,包括使用线程的sleep、join以及LockSupport的方法,但用户可能希望找到更高效或更可靠的方式。 首先,用户的需求是确保严格的顺序,即ABCABC...重复十次。常见的多线程问题,需要线程间的同步机制。之前的示例中,引用1使用了sleep,但这不可靠,因为线程调度不可控,可能导致顺序错乱。引用2用了join,每个线程结束后再启动下一个,但这样实际上变成了单线程,效率不高。引用3使用了LockSupport,通过唤醒特定线程来实现顺序,但代码可能比较复杂。 我需要考虑更合适的同步机制。常见的方法包括使用锁和条件变量,或者信号量(Semaphore)。信号量可能更适合这个问题,因为每个线程可以等待前一个线程的信号。比如,初始时,A线程可以执行,执行完后释放B的信号量,B执行后释放C,C执行后释放A,依此类推。 另外,需要确保每个字母打印十次,总共输出30次,形成10次ABC。可能需要一个共享的计数器,或者每个线程负责自己的十次循环,但需要协调顺序。 考虑到线程间的依赖,使用三个信号量可能更直接。例如,信号量A初始化为1,B和C为0。A线程在执行完打印后,释放B的信号量,B线程获取后执行,然后释放C,依此类推。这样每个线程在完成自己的任务后,触发下一个线程的执行。 此外,需要处理线程的启动顺序,确保所有线程都处于等待状态,然后按顺序触发。Java中的Semaphore类可以用于此目的。每个线程在开始前需要获取自己的信号量,执行后释放下一个线程的信号量。 可能的实现步骤: 1. 创建三个信号量,semA初始为1,semB和semC为0。 2. 线程A在打印前获取semA,打印后释放semB。 3. 线程B在打印前获取semB,打印后释放semC。 4. 线程C在打印前获取semC,打印后释放semA。 5. 循环十次,每个线程打印十次,但通过信号量的控制,确保顺序正确。 这样,每个信号量控制一个线程的执行权限,确保严格的顺序。同时,每个线程执行十次循环,每次循环都等待对应的信号量,从而保证顺序。 需要验证这样的逻辑是否正确,是否存在死锁或竞争条件。例如,当线程A第一次释放semB后,线程B是否能及时获取到信号量并执行。由于信号量的释放和获取是原子操作,应该不会有问题。同时,每个线程执行完十次后会自动结束,而主线程需要等待所有子线程完成。 另外,需要考虑Java中信号量的使用是否正确,例如acquire和release方法的调用。每个线程在自己的循环中获取信号量,打印,然后释放下一个线程的信号量。循环次数为10次,这样总共会打印30次,形成ABC十次。 最后,编写代码示例,并解释每个部分的作用,确保用户能够理解如何实现。</think>### 分步实现多线程顺序打印ABC(各10次) #### **方法选择:信号量控制法(推荐)** 通过信号量(Semaphore)实现线程间精准同步,每个线程执行后唤醒下一个线程,确保严格按ABC顺序输出。此方法效率高且资源消耗低。 --- ### **Java代码实现** ```java import java.util.concurrent.Semaphore; public class OrderedPrint { // 定义三个信号量:A初始可执行,B/C需等待 private static Semaphore semA = new Semaphore(1); private static Semaphore semB = new Semaphore(0); private static Semaphore semC = new Semaphore(0); private static final int PRINT_TIMES = 10; static class PrintA implements Runnable { @Override public void run() { try { for (int i = 0; i < PRINT_TIMES; i++) { semA.acquire(); // 等待A的信号量 System.out.print("A"); semB.release(); // 允许B执行 } } catch (InterruptedException e) { e.printStackTrace(); } } } static class PrintB implements Runnable { @Override public void run() { try { for (int i = 0; i < PRINT_TIMES; i++) { semB.acquire(); // 等待B的信号量 System.out.print("B"); semC.release(); // 允许C执行 } } catch (InterruptedException e) { e.printStackTrace(); } } } static class PrintC implements Runnable { @Override public void run() { try { for (int i = 0; i < PRINT_TIMES; i++) { semC.acquire(); // 等待C的信号量 System.out.println("C"); // 换行保证每组ABC独立显示 semA.release(); // 允许下一轮A执行 } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Thread(new PrintA()).start(); new Thread(new PrintB()).start(); new Thread(new PrintC()).start(); } } ``` --- ### **代码解析** 1. **信号量初始化**: - `semA`初始化为1,表示线程A可直接执行。 - `semB`和`semC`初始化为0,需等待前一线程释放信号量[^1]。 2. **线程逻辑**: - **线程A**:获取`semA`后打印"A",释放`semB`。 - **线程B**:获取`semB`后打印"B",释放`semC`。 - **线程C**:获取`semC`后打印"C"并换行,释放`semA`开启下一轮循环[^2]。 3. **循环控制**: - 每个线程循环10次,通过信号量协调执行顺序,最终输出10次`ABC`。 --- ### **其他实现方法对比** | 方法 | 优点 | 缺点 | |-------------------|--------------------------|-------------------------------| | **信号量控制法** | 精准同步,资源消耗低 | 需管理多个信号量 | | **join()方法** | 简单直观 | 效率低(线程串行执行)[^2] | | **LockSupport** | 直接控制线程唤醒/阻塞 | 需手动管理唤醒顺序[^3] | --- ### **扩展问题** 1. 如何实现N个线程按固定顺序循环打印? 2. 如果要求每个字母由不同类实现,如何解耦线程逻辑? 3. 信号量数量与线程数的关系是什么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值