3个线程交替输出打印1-100的编程题

    今天去某公司面试,其中有一道手写3个线程交替输出打印1-100的编程题。于是乎本码农不惧挑战,开工手写,写的过程中总觉得少了点什么,有些不对。

    做完笔试题后,面试管匆匆忙忙地赶来,电脑上的界面还停留在 IDEA 的界面。我和面试官寒暄几句后,就开始了具体的面试流程。

    不知道是不是去的太早了,打扰到了面试官调试代码。还是编程题因为纯手写,被找出了瑕疵。最终,今天的面试反馈结果没过。

 

废话不多说,上代码。

1. 利用synchronize 关键字、 object.wait 、 object.notifyAll 来实现

/**
 *
 * 〈3个线程交替打印1-100〉
 * @author cqwshzj
 * @create 2021/4/13
 * @since 1.0.0
 */
public class TestMain {


	public static void main(String[] args) {

		MyCounter counter = new MyCounter();

		final int limit = 110;
		int divisorNum = 3;
		Runnable worker0 = new PrintWorker( counter , limit, divisorNum, 0);
		Runnable worker1 = new PrintWorker( counter , limit, divisorNum, 1);
		Runnable worker2 = new PrintWorker( counter , limit, divisorNum, 2);

		final Thread thread0 = new Thread( worker0 );
		final Thread thread1 = new Thread( worker1 );
		final Thread thread2 = new Thread( worker2 );

		thread0.setName("Print0Worker");
		thread1.setName("Print1Worker");
		thread2.setName("Print2Worker");

		thread0.start();
		thread1.start();
		thread2.start();

	}



}


/** 计数器 */
class MyCounter {
	public volatile int num =1;
}


/** 打印对应余数的线程 */
class PrintWorker implements Runnable{
	/** 计数器 */
	private MyCounter myCounter;
	/** 总器 */
	private int limit = 9;
	/** 除数 */
	private int remainderNum;
	/** 余数 */
	private int divisorNum ;

	/**
	 *
	 * @param myCounter 计数器
	 * @param limit 总器
	 * @param divisorNum 除数
	 * @param remainderNum 余数
	 */
	public PrintWorker(MyCounter myCounter, int limit, int divisorNum, int remainderNum) {
		this.myCounter = myCounter;
		this.limit = limit;
		this.divisorNum = divisorNum;
		this.remainderNum = remainderNum;
	}

	@Override
	public void run() {
		while ( myCounter.num <= limit ){

			synchronized ( myCounter ){
				if ( myCounter.num % divisorNum == remainderNum ){
					System.out.println( Thread.currentThread().getName()+" ---> myCounter.num = " + myCounter.num);
					myCounter.num ++;
					myCounter.notifyAll();
				}else{
					try {
						myCounter.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

运行结果如下

Connected to the target VM, address: '127.0.0.1:58098', transport: 'socket'
Print1Worker ---> myCounter.num = 1
Print2Worker ---> myCounter.num = 2
Print0Worker ---> myCounter.num = 3
Print1Worker ---> myCounter.num = 4
Print2Worker ---> myCounter.num = 5
Print0Worker ---> myCounter.num = 6
Print1Worker ---> myCounter.num = 7
Print2Worker ---> myCounter.num = 8
Print0Worker ---> myCounter.num = 9
Print1Worker ---> myCounter.num = 10
Print2Worker ---> myCounter.num = 11
Print0Worker ---> myCounter.num = 12
Print1Worker ---> myCounter.num = 13
Print2Worker ---> myCounter.num = 14
Print0Worker ---> myCounter.num = 15
Print1Worker ---> myCounter.num = 16
Print2Worker ---> myCounter.num = 17
Print0Worker ---> myCounter.num = 18
Print1Worker ---> myCounter.num = 19
Print2Worker ---> myCounter.num = 20
Print0Worker ---> myCounter.num = 21
Print1Worker ---> myCounter.num = 22
Print2Worker ---> myCounter.num = 23
Print0Worker ---> myCounter.num = 24
Print1Worker ---> myCounter.num = 25
Print2Worker ---> myCounter.num = 26
Print0Worker ---> myCounter.num = 27
Print1Worker ---> myCounter.num = 28
Print2Worker ---> myCounter.num = 29
Print0Worker ---> myCounter.num = 30
Print1Worker ---> myCounter.num = 31
Print2Worker ---> myCounter.num = 32
Print0Worker ---> myCounter.num = 33
Print1Worker ---> myCounter.num = 34
Print2Worker ---> myCounter.num = 35
Print0Worker ---> myCounter.num = 36
Print1Worker ---> myCounter.num = 37
Print2Worker ---> myCounter.num = 38
Print0Worker ---> myCounter.num = 39
Print1Worker ---> myCounter.num = 40
Print2Worker ---> myCounter.num = 41
Print0Worker ---> myCounter.num = 42
Print1Worker ---> myCounter.num = 43
Print2Worker ---> myCounter.num = 44
Print0Worker ---> myCounter.num = 45
Print1Worker ---> myCounter.num = 46
Print2Worker ---> myCounter.num = 47
Print0Worker ---> myCounter.num = 48
Print1Worker ---> myCounter.num = 49
Print2Worker ---> myCounter.num = 50
Print0Worker ---> myCounter.num = 51
Print1Worker ---> myCounter.num = 52
Print2Worker ---> myCounter.num = 53
Print0Worker ---> myCounter.num = 54
Print1Worker ---> myCounter.num = 55
Print2Worker ---> myCounter.num = 56
Print0Worker ---> myCounter.num = 57
Print1Worker ---> myCounter.num = 58
Print2Worker ---> myCounter.num = 59
Print0Worker ---> myCounter.num = 60
Print1Worker ---> myCounter.num = 61
Print2Worker ---> myCounter.num = 62
Print0Worker ---> myCounter.num = 63
Print1Worker ---> myCounter.num = 64
Print2Worker ---> myCounter.num = 65
Print0Worker ---> myCounter.num = 66
Print1Worker ---> myCounter.num = 67
Print2Worker ---> myCounter.num = 68
Print0Worker ---> myCounter.num = 69
Print1Worker ---> myCounter.num = 70
Print2Worker ---> myCounter.num = 71
Print0Worker ---> myCounter.num = 72
Print1Worker ---> myCounter.num = 73
Print2Worker ---> myCounter.num = 74
Print0Worker ---> myCounter.num = 75
Print1Worker ---> myCounter.num = 76
Print2Worker ---> myCounter.num = 77
Print0Worker ---> myCounter.num = 78
Print1Worker ---> myCounter.num = 79
Print2Worker ---> myCounter.num = 80
Print0Worker ---> myCounter.num = 81
Print1Worker ---> myCounter.num = 82
Print2Worker ---> myCounter.num = 83
Print0Worker ---> myCounter.num = 84
Print1Worker ---> myCounter.num = 85
Print2Worker ---> myCounter.num = 86
Print0Worker ---> myCounter.num = 87
Print1Worker ---> myCounter.num = 88
Print2Worker ---> myCounter.num = 89
Print0Worker ---> myCounter.num = 90
Print1Worker ---> myCounter.num = 91
Print2Worker ---> myCounter.num = 92
Print0Worker ---> myCounter.num = 93
Print1Worker ---> myCounter.num = 94
Print2Worker ---> myCounter.num = 95
Print0Worker ---> myCounter.num = 96
Print1Worker ---> myCounter.num = 97
Print2Worker ---> myCounter.num = 98
Print0Worker ---> myCounter.num = 99
Print1Worker ---> myCounter.num = 100
Print2Worker ---> myCounter.num = 101
Print0Worker ---> myCounter.num = 102
Print1Worker ---> myCounter.num = 103
Print2Worker ---> myCounter.num = 104
Print0Worker ---> myCounter.num = 105
Print1Worker ---> myCounter.num = 106
Print2Worker ---> myCounter.num = 107
Print0Worker ---> myCounter.num = 108
Print1Worker ---> myCounter.num = 109
Print2Worker ---> myCounter.num = 110
Disconnected from the target VM, address: '127.0.0.1:58098', transport: 'socket'

Process finished with exit code 0

 

2. 利用 ReentrantLock 和 Condition 来实现

public class PrintReentrantLockConditionTest {

	public static void main(String[] args) {
		final ReentrantLock lock = new ReentrantLock();
		final Condition condition = lock.newCondition();

		final int startNum = 1;
		MyCounter counter = new MyCounter(startNum);

		final int endNum = 110;
		int divisorNum = 3;
		Runnable worker0 = new ReentrantLockPrintWorker( counter , endNum, divisorNum, 0, lock, condition);
		Runnable worker1 = new ReentrantLockPrintWorker( counter , endNum, divisorNum, 1, lock, condition);
		Runnable worker2 = new ReentrantLockPrintWorker( counter , endNum, divisorNum, 2, lock, condition);

		final Thread thread0 = new Thread( worker0 );
		final Thread thread1 = new Thread( worker1 );
		final Thread thread2 = new Thread( worker2 );

		thread0.setName("Print0Worker");
		thread1.setName("Print1Worker");
		thread2.setName("Print2Worker");

		thread0.start();
		thread1.start();
		thread2.start();


	}



}

/** 计数器 */
public class MyCounter {
	public volatile int num ;

	public MyCounter(int num) {
		this.num = num;
	}
}

/** 打印余数的线程 */
class ReentrantLockPrintWorker implements Runnable{

	/** 计数器 */
	private MyCounter myCounter;
	/** 总器 */
	private int endNum = 9;
	/** 除数 */
	private int remainderNum;
	/** 余数 */
	private int divisorNum ;

	//---------

	private ReentrantLock lock ;

	private Condition condition;

	public ReentrantLockPrintWorker(MyCounter myCounter,
									int endNum,
									int divisorNum,
									int remainderNum,
									ReentrantLock lock,
									Condition condition) {
		this.myCounter = myCounter;
		this.endNum = endNum;
		this.remainderNum = remainderNum;
		this.divisorNum = divisorNum;
		this.lock = lock;
		this.condition = condition;
	}

	//---------

	@Override
	public void run() {
		while ( myCounter.num <= endNum ){
			try {
				lock.lock();
				if ( myCounter.num % divisorNum == remainderNum ){
					System.out.println(Thread.currentThread().getName()+" --> myCounter.num = " + myCounter.num);
					myCounter.num++;
					condition.signalAll();
				}else{
					condition.await();
				}
			}catch (Exception e){
				e.printStackTrace();
			}finally {
				lock.unlock();
			}
		}
	}
}

运行效果


Print1Worker --> myCounter.num = 1
Print2Worker --> myCounter.num = 2
Print0Worker --> myCounter.num = 3
Print1Worker --> myCounter.num = 4
Print2Worker --> myCounter.num = 5
Print0Worker --> myCounter.num = 6
Print1Worker --> myCounter.num = 7
Print2Worker --> myCounter.num = 8
Print0Worker --> myCounter.num = 9
Print1Worker --> myCounter.num = 10
Print2Worker --> myCounter.num = 11
Print0Worker --> myCounter.num = 12
Print1Worker --> myCounter.num = 13
Print2Worker --> myCounter.num = 14
Print0Worker --> myCounter.num = 15
Print1Worker --> myCounter.num = 16
Print2Worker --> myCounter.num = 17
Print0Worker --> myCounter.num = 18
Print1Worker --> myCounter.num = 19
Print2Worker --> myCounter.num = 20
Print0Worker --> myCounter.num = 21
Print1Worker --> myCounter.num = 22
Print2Worker --> myCounter.num = 23
Print0Worker --> myCounter.num = 24
Print1Worker --> myCounter.num = 25
Print2Worker --> myCounter.num = 26
Print0Worker --> myCounter.num = 27
Print1Worker --> myCounter.num = 28
Print2Worker --> myCounter.num = 29
Print0Worker --> myCounter.num = 30
Print1Worker --> myCounter.num = 31
Print2Worker --> myCounter.num = 32
Print0Worker --> myCounter.num = 33
Print1Worker --> myCounter.num = 34
Print2Worker --> myCounter.num = 35
Print0Worker --> myCounter.num = 36
Print1Worker --> myCounter.num = 37
Print2Worker --> myCounter.num = 38
Print0Worker --> myCounter.num = 39
Print1Worker --> myCounter.num = 40
Print2Worker --> myCounter.num = 41
Print0Worker --> myCounter.num = 42
Print1Worker --> myCounter.num = 43
Print2Worker --> myCounter.num = 44
Print0Worker --> myCounter.num = 45
Print1Worker --> myCounter.num = 46
Print2Worker --> myCounter.num = 47
Print0Worker --> myCounter.num = 48
Print1Worker --> myCounter.num = 49
Print2Worker --> myCounter.num = 50
Print0Worker --> myCounter.num = 51
Print1Worker --> myCounter.num = 52
Print2Worker --> myCounter.num = 53
Print0Worker --> myCounter.num = 54
Print1Worker --> myCounter.num = 55
Print2Worker --> myCounter.num = 56
Print0Worker --> myCounter.num = 57
Print1Worker --> myCounter.num = 58
Print2Worker --> myCounter.num = 59
Print0Worker --> myCounter.num = 60
Print1Worker --> myCounter.num = 61
Print2Worker --> myCounter.num = 62
Print0Worker --> myCounter.num = 63
Print1Worker --> myCounter.num = 64
Print2Worker --> myCounter.num = 65
Print0Worker --> myCounter.num = 66
Print1Worker --> myCounter.num = 67
Print2Worker --> myCounter.num = 68
Print0Worker --> myCounter.num = 69
Print1Worker --> myCounter.num = 70
Print2Worker --> myCounter.num = 71
Print0Worker --> myCounter.num = 72
Print1Worker --> myCounter.num = 73
Print2Worker --> myCounter.num = 74
Print0Worker --> myCounter.num = 75
Print1Worker --> myCounter.num = 76
Print2Worker --> myCounter.num = 77
Print0Worker --> myCounter.num = 78
Print1Worker --> myCounter.num = 79
Print2Worker --> myCounter.num = 80
Print0Worker --> myCounter.num = 81
Print1Worker --> myCounter.num = 82
Print2Worker --> myCounter.num = 83
Print0Worker --> myCounter.num = 84
Print1Worker --> myCounter.num = 85
Print2Worker --> myCounter.num = 86
Print0Worker --> myCounter.num = 87
Print1Worker --> myCounter.num = 88
Print2Worker --> myCounter.num = 89
Print0Worker --> myCounter.num = 90
Print1Worker --> myCounter.num = 91
Print2Worker --> myCounter.num = 92
Print0Worker --> myCounter.num = 93
Print1Worker --> myCounter.num = 94
Print2Worker --> myCounter.num = 95
Print0Worker --> myCounter.num = 96
Print1Worker --> myCounter.num = 97
Print2Worker --> myCounter.num = 98
Print0Worker --> myCounter.num = 99
Print1Worker --> myCounter.num = 100
Print2Worker --> myCounter.num = 101
Print0Worker --> myCounter.num = 102
Print1Worker --> myCounter.num = 103
Print2Worker --> myCounter.num = 104
Print0Worker --> myCounter.num = 105
Print1Worker --> myCounter.num = 106
Print2Worker --> myCounter.num = 107
Print0Worker --> myCounter.num = 108
Print1Worker --> myCounter.num = 109
Print2Worker --> myCounter.num = 110
Disconnected from the target VM, address: '127.0.0.1:61346', transport: 'socket'

Process finished with exit code 0

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值