主线程和子线程均循环10次,两者交替运行50次

本文介绍了一种利用面向对象编程思想实现主子线程交互的方法。通过将主线程和子线程的功能封装到同一个类中,并使用同步方法来协调线程间的执行顺序,实现了线程之间的有序交替执行。

我们应该时时保持面向对象编程的思想,可以将主子线程封装到一个类中(类中的方法是两个有关联的方法)

,使用标记变量可以人为的控制线程的执行。


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;

import javax.print.attribute.standard.MediaName;
import javax.security.auth.Subject;
import javax.swing.plaf.nimbus.AbstractRegionPainter;

import org.omg.CORBA.PUBLIC_MEMBER;

class zz {
	public static void main(String[] args) {
		final Run running = new Run();
		new Thread(
			new Runnable() {
				public void run() {
					for(int i = 0;i < 50;++ i){
						running.subLine(i);
					}
				}
			}
		).start();
		for(int i = 0;i < 50;++ i){
			running.mainLine(i);
		}
	}
}

class Run{
	private boolean mainLineStart = true;
	public synchronized void subLine(int i){
		if(mainLineStart){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		for(int j = 0;j < 10;++ j){
			System.out.println("子线程第"+i+"轮次:"+j);
		}
		mainLineStart = true;
		this.notify();
	}
	
	
	public synchronized void  mainLine(int i){
		if(!mainLineStart){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		for(int j = 0;j < 10;++ j){
			System.out.println("主线程第"+i+"轮次:"+j);
		}
		mainLineStart = false;
		this.notify();
	}
}


<think>根据用户需求,需要编写一个程序,实现子线程循环3,然后主线程循环5,如此反复3。我们需要使用多线程的同步机制来控制线程执行顺序。可以使用`threading`模块中的`Lock`或者`Condition`。这里我们使用`Condition`来实现线程间的通信。 设计思路: 1. 创建一个条件锁`condition`。 2. 设置一个标志位`flag`,用于指示当前应该是子线程执行还是主线程执行。例如,当`flag`为0时子线程执行,为1时主线程执行。 3. 子线程的任务函数:循环3(整个大循环3),每执行前先获取条件锁,判断标志位,如果标志位不是0,则等待;如果是0,则执行子线程循环3,然后设置标志位为1,并通知其他线程主线程),然后等待。 4. 主线程执行:同样循环3,每获取条件锁,判断标志位,如果不是1则等待,如果是则执行主线程循环5,然后设置标志位为0,并通知子线程。 但是注意,整个流程需要重复3(即子线程循环3->主线程循环5,这个顺序重复3)。我们可以将子线程主线程的任务都放在一个循环3的大循环中。 然而,用户要求是“反复3”,也就是整个“子线程循环3主线程循环5”的过程重复3。因此,我们可以在子线程中完成3这样的交替(每交替包括子线程循环3主线程循环5),但是实际上主线程子线程是并发的,所以我们需要通过条件变量来控制。 另一种思路: 我们用一个线程子线程)来执行循环3”的任务,而主线程执行循环5”的任务,但是需要交替执行,并且整个交替过程重复3。 由于用户明确要求主线程子线程,所以我们创建的子线程执行子任务,而主线程执行主任务。 步骤: 1. 定义条件变量标志。 2. 创建子线程运行一个函数,该函数包含3循环(即整个交替过程3),每循环中: a. 获取条件锁 b. 如果标志位不是子线程执行的状态,则等待 c. 执行子线程循环3(打印或其他操作) d. 修改标志位,通知主线程 e. 然后等待条件(等待主线程完成) 3. 主线程执行完创建子线程后,也进行3循环,每循环中: a. 获取条件锁 b. 如果标志位不是主线程执行的状态,则等待 c. 执行主线程循环5 d. 修改标志位,通知子线程 e. 然后等待条件(等待子线程下一) 注意:初始状态应该是子线程执行,所以标志位初始设为0(表示子线程可以执行)。 但是这里有一个问题:主线程子线程的大循环交替执行的,总共3交替,每交替包括子线程循环3主线程循环5。 然而,用户要求的顺序是:子线程循环3 -> 主线程循环5 -> 子线程循环3 -> 主线程循环5 -> 子线程循环3 -> 主线程循环5。 因此,我们可以这样设计: - 子线程函数: for i in range(3): # 整个交替过程3 with condition: while flag != 0: # 如果不是子线程执行的条件,则等待 condition.wait() # 子线程循环3 for j in range(3): print(f"子线程执行: 第{j+1}") # 设置标志位,通知主线程执行 flag = 1 condition.notify() - 主线程(在启动子线程后): for i in range(3): # 整个交替过程3 with condition: while flag != 1: condition.wait() # 主线程循环5 for j in range(5): print(f"主线程执行: 第{j+1}") # 设置标志位,通知子线程执行 flag = 0 condition.notify() 但是这样有一个问题:第一执行时,子线程拿到锁后执行,然后主线程在第一循环时因为flag=1而等待。然而,当子线程执行完第一循环(即打印3)后,将flag设为1,并通知(唤醒)主线程。然后子线程会继续下一循环(i=1),但是此时flag已经被主线程改了吗?并没有,因为主线程刚刚被唤醒,还没有执行。所以子线程在第二循环时,会再判断flag,此时flag为1,所以子线程会等待。这样是正确的。 但是,当主线程执行完第一循环(打印5)后,将flag设为0,并通知子线程,然后主线程进入下一循环(i=1),但是下一循环一开始它又会等待,因为flag=0(不是1),所以主线程等待。这样就实现了交替。 但是,我们一共需要3交替,所以子线程主线程循环都是3(整个交替过程3)。 然而,这里还有一个问题:在最后一交替后,子线程执行完3循环(整个交替3)后退出,而主线程执行完3后也退出。这样是正常的。 但是,我们需要在主线程中等待子线程结束吗?这里我们不需要,因为主线程自己也要执行任务。不过,我们可以在主线程的最后使用`thread.join()`等待子线程结束。 但是,由于整个交替过程是3子线程主线程都会执行3循环,所以我们可以让子线程运行完3后结束,主线程在3后也结束,然后主线程等待子线程结束。 但是注意:在第三交替时,子线程执行完后将flag设为1,并通知主线程,然后子线程就结束了。主线程被唤醒后执行第三循环(打印5),然后也结束。 所以,我们需要在启动子线程后,主线程执行完3循环后,等待子线程结束。 但是,子线程已经结束了,所以`join`不会阻塞。 另外,我们还需要考虑初始状态:子线程执行,所以初始flag=0。 代码示例: ```python import threading # 创建条件变量 condition = threading.Condition() flag = 0 # 0表示子线程执行,1表示主线程执行 def child_task(): global flag for i in range(3): # 整个交替过程3 with condition: # 等待flag变为0(即轮到子线程执行) while flag != 0: condition.wait() # 子线程循环3 for j in range(3): print(f"子线程循环: 第{i+1}循环中的第{j+1}") # 执行完毕,将flag置为1,唤醒主线程 flag = 1 condition.notify() def main_task(): global flag for i in range(3): # 整个交替过程3 with condition: # 等待flag变为1(即轮到主线程执行) while flag != 1: condition.wait() # 主线程循环5 for j in range(5): print(f"主线程循环: 第{i+1}循环中的第{j+1}") # 执行完毕,将flag置为0,唤醒子线程 flag = 0 condition.notify() if __name__ == '__main__': # 创建并启动子线程 child_thread = threading.Thread(target=child_task) child_thread.start() # 主线程执行任务 main_task() # 等待子线程结束 child_thread.join() print("程序结束") ``` 但是,这里有一个问题:在主线程第一执行`main_task`时,一开始flag是0,所以主线程会等待。然后子线程首先获取到锁(因为主线程在等待时释放了锁),然后执行子线程的任务。这符合预期。 然而,我们需要注意:在第一交替中,子线程执行完后将flag置为1并通知主线程,然后子线程的第一循环结束,进入第二循环,但是此时在第二循环的开始,它判断flag=1(因为上一已经设为1了)所以子线程会等待。然后主线程被唤醒,执行主线程的第一循环循环5),然后设置flag=0并通知子线程。接着主线程进入第二循环,因为flag=0,所以主线程等待。然后子线程被唤醒,开始执行第二循环循环3)...直到3交替完成。 因此,上面的代码应该可以满足要求。 但是,由于条件变量的等待必须在持有锁的情况下,而`with condition`已经保证了锁的获取释放。 另外,打印信息中我们标识了是第几循环中的第几循环,这样更清晰。 测试:运行代码,输出应该是: 子线程循环: 第1循环中的第1 子线程循环: 第1循环中的第2 子线程循环: 第1循环中的第3 主线程循环: 第1循环中的第1 主线程循环: 第1循环中的第2 ...(主线程5子线程循环: 第2循环中的第1 ...(子线程3主线程循环: 第2循环中的第1 ...(主线程5子线程循环: 第3循环中的第1 ...(子线程3主线程循环: 第3循环中的第1 ...(主线程5) 共3轮,每轮都是先子线程3,然后主线程5。 但是,我们需要注意的是,在最后一主线程执行完后,子线程已经结束(因为它只循环3循环),而主线程执行完了3循环,所以程序正常结束。 这个程序满足要求。 然而,我们也可以考虑另一种实现:使用两个条件变量,但是没有必要,一个标志位一个条件变量足够。 另外,注意打印的信息可能会交错,因为子线程主线程交替执行,但是在我们这个程序中,由于控制严格交替,所以打印不会交错(因为每个线程执行时都是连续打印,不会被打断)。 但是,如果多个线程同时打印,控制台输出可能会乱序,但由于我们使用了条件变量,在同一时刻只有一个线程执行打印(因为每打印都在条件变量的保护下,而且是连续的循环),所以打印不会乱。 因此,我们输出上述代码。 但是,用户要求的是“子线程循环3,接着主线程循环5,如此反复,循环3”,这里的大循环(反复3)指的是整个交替过程3,所以上面的代码正确。 运行验证即可。 注意:全局变量`flag``condition`需要被两个线程共享。 我们使用`global`声明,但是注意在函数内部修改全局变量需要`global`,读取也需要吗?在函数内部如果只是读取,可以不使用`global`,但是如果要修改,必须使用`global`。这里两个函数中都需要修改`flag`,所以都需要`global flag`。 因此,代码如上。 </think># 多线程交替执行控制实现 下面我将实现一个程序,让子线程循环3主线程循环5,如此反复3。这个程序使用了线程同步机制来精确控制线程执行顺序。 ```python import threading import time # 创建条件变量锁 condition = threading.Condition() # 标志位:0表示子线程执行,1表示主线程执行 flag = 0 # 大循环计数器 cycle_count = 0 def child_thread_task(): """子线程任务函数""" global flag, cycle_count for _ in range(3): # 整个交替过程执行3 with condition: # 等待主线程通知 while flag != 0: condition.wait() # 子线程内部循环3 for i in range(1, 4): print(f"🌱 子线程执行: 第{cycle_count+1}轮的第{i}循环") time.sleep(0.1) # 模拟处理时间 # 准备切换到主线程 flag = 1 condition.notify() # 通知主线程 def main_thread_task(): """主线程任务函数""" global flag, cycle_count for _ in range(3): # 整个交替过程执行3 with condition: # 等待子线程通知 while flag != 1: condition.wait() # 主线程内部循环5 for i in range(1, 6): print(f"🚀 主线程执行: 第{cycle_count+1}轮的第{i}循环") time.sleep(0.1) # 模拟处理时间 # 准备切换到子线程 flag = 0 cycle_count += 1 condition.notify() # 通知子线程 if __name__ == "__main__": # 创建并启动子线程 child_thread = threading.Thread(target=child_thread_task) child_thread.start() # 主线程执行任务 main_thread_task() # 等待子线程结束 child_thread.join() print("\n✅ 所有线程执行完成!") ``` ## 程序说明 ### 关键设计原理 1. **线程同步机制**: - 使用`threading.Condition()`创建条件变量 - `flag`变量作为状态指示器(0=子线程执行,1=主线程执行) - `condition.wait()`使线程进入等待状态 - `condition.notify()`唤醒等待的线程 2. **执行流程控制**: ```mermaid graph TD A[开始] --> B[初始化flag=0] B --> C[子线程执行3] C --> D[设置flag=1, 通知主线程] D --> E[主线程执行5] E --> F[设置flag=0, 循环计数+1] F --> G{循环数<3?} G -- 是 --> C G -- 否 --> H[结束] ``` ### 输出示例 ``` 🌱 子线程执行: 第1轮的第1循环 🌱 子线程执行: 第1轮的第2循环 🌱 子线程执行: 第1轮的第3循环 🚀 主线程执行: 第1轮的第1循环 🚀 主线程执行: 第1轮的第2循环 🚀 主线程执行: 第1轮的第3循环 🚀 主线程执行: 第1轮的第4循环 🚀 主线程执行: 第1轮的第5循环 🌱 子线程执行: 第2轮的第1循环 🌱 子线程执行: 第2轮的第2循环 🌱 子线程执行: 第2轮的第3循环 🚀 主线程执行: 第2轮的第1循环 🚀 主线程执行: 第2轮的第2循环 🚀 主线程执行: 第2轮的第3循环 🚀 主线程执行: 第2轮的第4循环 🚀 主线程执行: 第2轮的第5循环 🌱 子线程执行: 第3轮的第1循环 🌱 子线程执行: 第3轮的第2循环 🌱 子线程执行: 第3轮的第3循环 🚀 主线程执行: 第3轮的第1循环 🚀 主线程执行: 第3轮的第2循环 🚀 主线程执行: 第3轮的第3循环 🚀 主线程执行: 第3轮的第4循环 🚀 主线程执行: 第3轮的第5循环 ✅ 所有线程执行完成! ``` ## 相关知识点 1. **Condition对象**: - Python提供的线程同步原语 - 包含一个锁(Lock或RLock)等待/通知机制 - 调用`wait()`会释放锁并进入等待状态 - 调用`notify()`会唤醒一个等待的线程 2. **线程安全**: - 使用`with condition:`确保代码块原子执行 - 避免多线程同时修改共享状态导致的竞态条件 - 保证了子线程主线程的精确交替执行[^2] 3. **全局变量保护**: - 使用`global`关键字访问全局变量 - 所有修改操作都在锁的保护下进行 - 确保状态一致性[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值