Java笔试题--用两个线程交叉打印(0~100)间的奇数和偶数

题目分析
完成本题所需要的条件:

  1. 需要两个线程,一个线程打印奇数,一个线程打印偶数;
  2. 当奇数打印线程在执行打印操作时,偶数打印线程需要处于阻塞状态;
  3. 当奇数线程打印操作完成后,需要唤醒偶数线程,并进入阻塞状态(释放锁),让偶数线程开始打印。

条件分析结果

通过分析条件2、3,可以确定是线程间的通信问题,所以首先需要建立两个线程,而且两个线程必须共享同一把锁(为了实现线程间的通信),并且需要一个标记状态来分辨哪一个线程在执行,哪一个线程需要阻塞。
(其实也可以通过判断当前打印数是否是奇数或是偶数,来判断线程的状态,本文使用的是标记来实现线程状态区分)

实现代码

为了方便分析本文把线程操作实现类放在了同一个文件中

package thread;
/**
 * 线程交替打印奇偶数
 * @author zcl
 *
 */
// 切记线程中的通信必须是共享一把锁的

// 共享类
class Num{
	// 需要打印的数字 初始化为0
	int num = 0;
	// 打印奇数还是偶数的判定条件,也是线程间通信的条件
	// true和false的设定,根据打印奇数还是偶数开头进行设定
	boolean flag = true;
}
/**
 * 偶数打印线程实现类
 * @author zcl
 */
class Even implements Runnable {
	// 共享对象 实现锁的共享
	private Num n;
	public Even(Num n) {
		super();
		this.n = n;
	}
	@Override
	public void run() {
		try {
			// 打印的边界
			while (n.num < 100) {
				// n为共享对象 为了实现两个线程 共享同一把锁
				// 锁住对象n只有一个线程可以执行
				synchronized (n) {
					// 如果是true 则是开始打印偶数 因为我们初始值设置的是0
					if (n.flag) {
						System.out.println(Thread.currentThread().getName()+"执行,获取偶数:" + n.num);
						// 打印之后对数字进行+1操作
						n.num++;
						// 将判定条件修改为false 目的是使当前线程等待
						n.flag = false; 
						// 唤醒奇数线程 只有两个线程所以使用notify就够了
						n.notify();
					} else {
						// 偶数打印线程进入阻塞状态 释放锁(奇数打印线程开始拿到锁进行打印)
						n.wait();
					}
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
/**
 * 奇数打印线程实现类(分析过程如偶数打印线程)
 * @author zcl
 */
class Odd implements Runnable {
	private Num n;
	public Odd(Num n) {
		super();
		this.n = n;
	}
	@Override
	public void run() {
		try {
			while (n.num < 100) {
				synchronized (n) {
				// 此处一开始flag我们设定为true,所以如果奇数线程先执行,会直接进入else,成为阻塞状态
					if (!n.flag) {
						System.out.println(Thread.currentThread().getName()+"执行,获取奇数:" + n.num);
						n.num++;
						n.flag = true;
						// 唤醒偶数线程
						n.notify();
					} else {
						n.wait();
					}
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

public class ThreadNumber {
	public static void main(String[] args) {
	// 新建一个线程共享对象
		Num num = new Num();
		
		Odd odd = new Odd(num);
		Even even = new Even(num);
		// 建立奇数线程
		Thread t1 = new Thread(odd);
		// 建立偶数线程
		Thread t2 = new Thread(even);
		
		t1.setName("奇数线程");
		t2.setName("偶数线程");
		
		// 分别开启两个个线程
		t1.start();
		t2.start();
	}
}


控制台打印结果

偶数线程执行,获取偶数:0
奇数线程执行,获取奇数:1
偶数线程执行,获取偶数:2
奇数线程执行,获取奇数:3
偶数线程执行,获取偶数:4
奇数线程执行,获取奇数:5
偶数线程执行,获取偶数:6
奇数线程执行,获取奇数:7
偶数线程执行,获取偶数:8
奇数线程执行,获取奇数:9
偶数线程执行,获取偶数:10
奇数线程执行,获取奇数:11
偶数线程执行,获取偶数:12
奇数线程执行,获取奇数:13
偶数线程执行,获取偶数:14
奇数线程执行,获取奇数:15
偶数线程执行,获取偶数:16
奇数线程执行,获取奇数:17
偶数线程执行,获取偶数:18
奇数线程执行,获取奇数:19
偶数线程执行,获取偶数:20
奇数线程执行,获取奇数:21
偶数线程执行,获取偶数:22
奇数线程执行,获取奇数:23
偶数线程执行,获取偶数:24
奇数线程执行,获取奇数:25
偶数线程执行,获取偶数:26
奇数线程执行,获取奇数:27
偶数线程执行,获取偶数:28
奇数线程执行,获取奇数:29
偶数线程执行,获取偶数:30
奇数线程执行,获取奇数:31
偶数线程执行,获取偶数:32
奇数线程执行,获取奇数:33
偶数线程执行,获取偶数:34
奇数线程执行,获取奇数:35
偶数线程执行,获取偶数:36
奇数线程执行,获取奇数:37
偶数线程执行,获取偶数:38
奇数线程执行,获取奇数:39
偶数线程执行,获取偶数:40
奇数线程执行,获取奇数:41
偶数线程执行,获取偶数:42
奇数线程执行,获取奇数:43
偶数线程执行,获取偶数:44
奇数线程执行,获取奇数:45
偶数线程执行,获取偶数:46
奇数线程执行,获取奇数:47
偶数线程执行,获取偶数:48
奇数线程执行,获取奇数:49
偶数线程执行,获取偶数:50
奇数线程执行,获取奇数:51
偶数线程执行,获取偶数:52
奇数线程执行,获取奇数:53
偶数线程执行,获取偶数:54
奇数线程执行,获取奇数:55
偶数线程执行,获取偶数:56
奇数线程执行,获取奇数:57
偶数线程执行,获取偶数:58
奇数线程执行,获取奇数:59
偶数线程执行,获取偶数:60
奇数线程执行,获取奇数:61
偶数线程执行,获取偶数:62
奇数线程执行,获取奇数:63
偶数线程执行,获取偶数:64
奇数线程执行,获取奇数:65
偶数线程执行,获取偶数:66
奇数线程执行,获取奇数:67
偶数线程执行,获取偶数:68
奇数线程执行,获取奇数:69
偶数线程执行,获取偶数:70
奇数线程执行,获取奇数:71
偶数线程执行,获取偶数:72
奇数线程执行,获取奇数:73
偶数线程执行,获取偶数:74
奇数线程执行,获取奇数:75
偶数线程执行,获取偶数:76
奇数线程执行,获取奇数:77
偶数线程执行,获取偶数:78
奇数线程执行,获取奇数:79
偶数线程执行,获取偶数:80
奇数线程执行,获取奇数:81
偶数线程执行,获取偶数:82
奇数线程执行,获取奇数:83
偶数线程执行,获取偶数:84
奇数线程执行,获取奇数:85
偶数线程执行,获取偶数:86
奇数线程执行,获取奇数:87
偶数线程执行,获取偶数:88
奇数线程执行,获取奇数:89
偶数线程执行,获取偶数:90
奇数线程执行,获取奇数:91
偶数线程执行,获取偶数:92
奇数线程执行,获取奇数:93
偶数线程执行,获取偶数:94
奇数线程执行,获取奇数:95
偶数线程执行,获取偶数:96
奇数线程执行,获取奇数:97
偶数线程执行,获取偶数:98
奇数线程执行,获取奇数:99

总结

交替执行线程,瞄准线程的通信准没错。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值