每个对象实例仅创建一个线程?AsyncCommand类线程同步代码解析
AsyncCommand类线程同步逻辑解析与代码补全
咱们先一步步拆解这段代码的核心目标:让两个线程交替打印递增的数字——一个线程负责输出奇数,另一个负责输出偶数,通过synchronized、wait()和notify()实现线程间的协作。
现有代码逻辑拆解
先看已经实现的线程t(奇数打印线程):
Thread t = new Thread(new Runnable() { @Override public void run() { while(true){ synchronized (lock) { try { // 如果当前i是偶数,说明轮到另一个线程处理,释放锁进入等待 if(i%2 ==0){ lock.wait(); } System.out.println(i); // 打印奇数 Thread.sleep(1000); // 模拟业务耗时 i++; // 数字自增 lock.notify(); // 唤醒等待的线程(也就是偶数线程) } catch (InterruptedException e) { e.printStackTrace(); } } } } });
这个线程的逻辑很清晰:每次拿到lock锁后,先检查当前数字是不是偶数,如果是就释放锁等待;如果是奇数就打印、自增,然后唤醒另一个线程。
再看被截断的线程t1(偶数打印线程),现有代码只写了等待条件:
Thread t1=new Thread(new Runnable() { @Override public void run() { while(true){ synchronized (lock) { try { // 如果当前i是奇数,说明还没轮到自己,释放锁等待 if(i%2 !=0){ lock.wait(); } // --- 此处需要补全的代码 --- } catch (InterruptedException e) { e.printStackTrace(); } } } } });
补全t1的代码并解析
按照和t线程对称的逻辑,t1线程拿到锁后,确认i是偶数时,就执行打印、自增、唤醒操作:
// 补全后的代码块 System.out.println(i); // 打印偶数 Thread.sleep(1000); // 同样模拟耗时 i++; // 数字自增 lock.notify(); // 唤醒等待的奇数线程
补全后,整个t1的run方法逻辑就完整了:当i是奇数时等待,直到被t线程唤醒;拿到执行权后打印偶数、自增,再唤醒t线程,形成交替执行的循环。
关键同步点说明
- 锁对象
lock:两个线程共用同一个lock对象作为同步监视器,确保同一时间只有一个线程能进入同步代码块。 wait()的作用:调用wait()时,线程会释放持有的锁,进入该锁的等待队列,直到被其他线程的notify()唤醒。notify()的作用:唤醒该锁等待队列中的一个线程(这里只有两个线程,所以必然唤醒另一个),被唤醒的线程需要重新获取锁才能继续执行。- 优化建议:这里用
if判断等待条件其实存在风险——如果线程被虚假唤醒(比如没收到notify()就被唤醒),会导致逻辑错误。更严谨的写法应该把if换成while,比如t线程里写成while(i%2 ==0){ lock.wait(); },t1里写成while(i%2 !=0){ lock.wait(); },这样即使被虚假唤醒,也会重新检查条件,确保逻辑正确。
内容的提问来源于stack exchange,提问作者Vivek Singh
相关产品推荐
相关产品推荐

