面试题--三个线程循环打印ABC10次的几种解决方法

本文介绍了三种使用Java实现多线程按顺序打印ABC的方法。第一种利用synchronized关键字和wait/notifyAll方法;第二种采用ReentrantLock和Condition来实现线程间的等待与唤醒;第三种则是通过Semaphore信号量控制线程的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一

       首先要确定临界资源,然后进行同步,与临界资源的不同要进行阻塞,相同的输出,并进行相应的调整

      

package mypack;
//临界类
public class Letters {
	private char letter='A';
	
	public void nextLetter(){
	  if(letter=='A')
		  letter='B';
	  else if(letter=='B')
		  letter='C';
	  else letter='A';
	}
	public char getLetter(){
		return letter;
	}
	public void print(){
		System.out.print(letter+" ");
	}

}

package mypack;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PrintLetters {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Letters letters=new Letters();
		ExecutorService exec = Executors.newFixedThreadPool(3);
		exec.execute(new ThreadPrint(letters,'A'));
		exec.execute(new ThreadPrint(letters,'B'));
		exec.execute(new ThreadPrint(letters,'C'));
		exec.shutdown();
	}

}
class ThreadPrint implements Runnable{
	private Letters letters;
	private char name;
	public ThreadPrint(Letters l,char ch){
		letters=l;
		name=ch;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try{
		for(int i=0;i<10;i++){
			synchronized(letters){
				while(letters.getLetter()!=name)//注意这里要用getLetter()的方法,随时获得临界资源变化的信息
					letters.wait();
				letters.print();
				letters.nextLetter();
				letters.notifyAll();
		    }
		  }
		}catch(InterruptedException e){
			System.out.println("Interrupted");
		}
	}
	
}
方法二:

  运用内部类,访问临界变量,不需要传递临界变量

package mypack;

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

public class PrintLetters {
	private char currLetter='A';
	private ReentrantLock lock=new ReentrantLock();
	private Condition conditionA=lock.newCondition();
	private Condition conditionB=lock.newCondition();
	private Condition conditionC=lock.newCondition();

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PrintLetters letters = new PrintLetters();
		ExecutorService exec = Executors.newFixedThreadPool(3);
		exec.execute(letters.new ThreadA('A'));
		exec.execute(letters.new ThreadB('B'));
		exec.execute(letters.new ThreadC('C'));
		exec.shutdown();
	}
	private class ThreadA implements Runnable{
		private char name;
		public ThreadA(char ch){
			name=ch;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			
			  for(int i=0;i<10;i++){
				try{
				lock.lock();
				while(currLetter!=name)
					try {
						conditionA.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.print(name);
				currLetter='B';
				conditionB.signal();
				}finally{
					lock.unlock();
				}
			  }
		}
	}
	
	private class ThreadB implements Runnable{
		private char name;
		public ThreadB(char ch){
			name=ch;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			  for(int i=0;i<10;i++){
			   try{
				lock.lock();
				while(currLetter!=name)
					try {
						conditionB.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.print(name);
				currLetter='C';
				conditionC.signal();
			   }
			  finally{
				lock.unlock();
			  }
		}
	}
}

	private class ThreadC implements Runnable{
		private char name;
		public ThreadC(char ch){
			name=ch;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			  for(int i=0;i<10;i++){
			  try{
				lock.lock();
				while(currLetter!=name)
					try {
						conditionC.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.print(name+" ");
				currLetter='A';
				conditionA.signal();
			  }
			  finally{
				lock.unlock();
			}
		}
	}
}
}

运用信号量Semaphore

package mypack;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class PrintLetters {
	private Semaphore semaphoreA=new Semaphore(1);
	private Semaphore semaphoreB=new Semaphore(0);
	private Semaphore semaphoreC=new Semaphore(0);

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PrintLetters letters = new PrintLetters();
		ExecutorService exec = Executors.newFixedThreadPool(3);
		exec.execute(letters.new ThreadA());
		exec.execute(letters.new ThreadB());
		exec.execute(letters.new ThreadC());
<span style="white-space:pre">		</span>exec.shutdown();
	}
	private class ThreadA implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i=0;i<10;i++){
				try {
					semaphoreA.acquire();
					System.out.print('A');
					semaphoreB.release();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	private class ThreadB implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i=0;i<10;i++){
				try {
					semaphoreB.acquire();
					System.out.print('B');
					semaphoreC.release();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	private class ThreadC implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i=0;i<10;i++){
				try {
					semaphoreC.acquire();
					System.out.println("C  ");
					semaphoreA.release();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
		
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值