第五天 : 启动线程和运行线程中方法的区别

本文详细介绍了Java中进程与线程的概念,通过实例演示了如何使用run()方法执行代码片段及start()方法启动线程。文章对比了直接调用run()方法与通过start()方法启动线程的区别,阐述了两种方式下线程执行的不同行为。
进程:在系统中应用程序的执行都会用内存,每个应用程序都是一个进程;

线程:每个进程在运行的时候都有多个线程会执行,java的优点就是多线程

 

run()方法里面放的是执行的代码片段;

start()方法是线程的启动方法;

package -------------
public class Demo01 {
	int i;
	public static void main(String[] args) {
		Demo01.Thread1 t=new Demo01().new Thread1();
		Demo01.Thread1 t1=new Demo01().new Thread1();
		
		t.run();
		t1.run();
		t.start();
		t1.start();
	}
	
class Thread1 extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(i=0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+"---i="+i);
			try {
				sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}
}

分析结果可知:

对象执行run(),只有一个主线程main按照代码的顺序自顶层往下层开始执行

对象执行start(),线程开始就绪,线程调解器利用线程调度系统开始交互的执行线程中的run()

总结:调用run()是顺序执行,调用start()是交互执行;

 

 

<think>我们正在处理一个关于C#中线程异常的特定问题:System.Threading.ThreadStateException,错误信息为“线程正在运行或被终止;它无法重新启动”。用户已经提供了引用[1],其中解释了线程状态以及ThreadState的各种可能值。根据上下文,用户之前询问过线程挂起终止的作用,现在遇到了这个异常,需要解决方案。 原因分析: 根据错误信息,这个异常通常发生在尝试重新启动一个已经处于运行中或已终止状态的线程时。在C#中,一个线程只能启动一次(即调用Start方法一次)。当我们尝试第二次调用Start方法时,就会抛出ThreadStateException。 引用[1]中明确指出: - Unstarted:未调用Thread.Start()开始线程运行 - Running:线程正在正常运行 - Stopped:线程已经被停止 - Aborted:线程已停止 因此,当我们尝试重新启动一个已经启动(Running)或者已经停止(Stopped/Aborted)的线程时,就会触发此异常。 解决方案: 我们需要确保一个线程启动一次。如果我们需要多次执行类似的任务,应该创建一个新的线程实例,而不是重复使用同一个线程实例。 步骤: 1. 不要重复使用同一个线程对象:一旦线程已经启动并完成(或终止),该线程对象就不能再被启动。如果我们需要再次执行相同的任务,应该创建一个新的Thread对象。 2. 检查线程状态:在启动线程之前,可以通过检查Thread.ThreadState属性来避免此异常。但是,由于线程状态可能变化,更好的做法是设计逻辑避免重复启动。 3. 使用标志位控制:如果我们希望线程能够重复执行任务,可以考虑使用循环重置,但注意线程对象本身不能重启,所以通常我们会让线程执行一个循环,然后通过信号控制暂停继续,而不是结束线程。但是,如果需要多次启动,则每次都应该创建新线程。 示例代码: 错误示例: ```csharp Thread myThread = new Thread(MyThreadMethod); myThread.Start(); // ... 一段时间后,再次尝试启动同一个线程实例 myThread.Start(); // 这里会抛出ThreadStateException ``` 正确做法: ```csharp // 需要多次执行时,每次都创建新线程 Thread myThread = new Thread(MyThreadMethod); myThread.Start(); // 当需要再次执行同样的方法时,重新创建一个新的线程 myThread = new Thread(MyThreadMethod); // 注意:这里创建了新线程 myThread.Start(); ``` 另一种常见情形:我们可能希望线程执行完成后重新启动,但实际上线程完成后的状态是Stopped,无法再次启动。我们可以考虑在任务方法中使用循环,但这样线程就会一直运行直到我们终止它。或者,我们可以使用线程池(ThreadPool)或任务(Task)来执行需要重复执行的工作,因为它们可以复用线程。 推荐使用Task(.NET 4.0+): 使用Task可以避免直接管理线程的生命周期,并且可以重复调度(但注意,一个Task实例也是只能运行一次,如果需要多次运行,可以创建多个Task实例,或者使用循环内部的任务)。 例如: ```csharp Task.Run(MyThreadMethod); // 第一次运行 // 需要再次运行 Task.Run(MyThreadMethod); // 创建一个新任务运行 ``` 或者,使用一个循环任务(注意:这里每次运行都是一个新的任务): ```csharp // 使用Task.Run多次调用 for (int i = 0; i < 10; i++) { Task.Run(MyThreadMethod); } ``` 总结: 根本原因是试图重新启动一个已经启动过或已经结束的线程。解决方法是每次执行都创建新的线程实例(或使用任务),或者改变设计,让线程内部循环执行任务(通过信号控制暂停继续),而不是结束线程后再次启动。 注意:在旧的代码中可能会看到通过检查状态来避免,但这并非可靠,因为状态可能会在检查后改变。而且,即使状态是Stopped,也不能重新启动。 引用[1]中关于线程状态的描述可以作为参考,特别是Stopped状态表示线程已经停止,此时再调用Start会导致异常。 相关问题: 根据用户之前的问题当前问题,我们可以生成以下相关问题: §§相关问题§§ 1. C#中如何正确终止一个正在运行线程? 2. 如何使用Task替代Thread来实现多线程? 3. 线程的状态转换是怎样的?哪些状态可以转换为运行状态? 4. 如何避免线程的重复启动异常? </think>### C#中线程状态异常解决方案 #### 异常原因分析 当出现`System.Threading.ThreadStateException: "线程正在运行或被终止;它无法重新启动"`错误时,通常由以下原因导致: 1. **重复启动线程** 尝试对已完成执行或已被终止的线程再次调用`.Start()`方法[^1] ```csharp Thread t = new Thread(Work); t.Start(); // 正常运行 t.Start(); // ❌ 第二次调用触发异常 ``` 2. **状态检查缺失** 未验证线程状态就执行操作: ```csharp if (t.ThreadState == ThreadState.Running) { t.Abort(); // 运行时终止 } t.Start(); // ❌ 终止后重启会异常 ``` 3. **线程池对象复用** 错误复用线程实例: ```csharp for (int i = 0; i < 5; i++) { Thread t = new Thread(Work); t.Start(); // 首次正常 t.Join(); // 等待结束 t.Start(); // ❌ 循环中复用已终止线程 } ``` #### 解决方案 ##### 方法1:创建新线程实例(推荐) ```csharp void ExecuteTask() { // ❌ 错误:重用已结束线程 // ✅ 正确:每次创建新实例 Thread worker = new Thread(DoWork); worker.Start(); } ``` ##### 方法2:线程状态检查 ```csharp void SafeStart(Thread t) { // 检查线程状态[^1] if (t.ThreadState.HasFlag(ThreadState.Unstarted)) { t.Start(); } else { // 创建新线程替代重启 Thread newWorker = new Thread(DoWork); newWorker.Start(); } } ``` ##### 方法3:使用线程池/Task ```csharp // 适合重复执行的短任务 ThreadPool.QueueUserWorkItem(state => DoWork()); // .NET 4.0+ 推荐方案 Task.Run(() => DoWork()); ``` ##### 方法4:线程生命周期管理 ```csharp class WorkerManager { private Thread _worker; private bool _isRunning = false; public void Start() { if (_isRunning) return; _worker = new Thread(() => { _isRunning = true; try { /* 工作代码 */ } finally { _isRunning = false; } }); _worker.Start(); } } ``` #### 关键注意事项 1. **线程状态图谱** ``` Unstarted → Running → (WaitSleepJoin) → Stopped ↑ ↓ AbortRequested → Aborted ``` 2. **线程对象生命周期规则** - 每个线程实例只能启动一次 - 终止后的线程无法重启 - `ThreadState.Stopped`状态不可逆转[^1] 3. **替代方案优先级** ```mermaid graph TD A[需要执行任务] --> B{需重复执行?} B -->|是| C[Task.Run] B -->|否| D[new Thread] D --> E[单次执行] ``` > 💡 **最佳实践**:在.NET Core 3.0+中,优先使用`Task`替代`Thread`,避免状态管理问题。线程池会自动处理线程复用,无需手动管理生命周期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值