Thread详解

本文介绍了Java中创建线程的多种方式,包括继承Thread类、实现Runnable接口、使用Callable和Future,以及线程的生命周期管理。此外还探讨了如何控制线程执行,如线程的睡眠、让步、优先级调整等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.继承THread类创建线程类

<span style="font-family:Times New Roman;font-size:18px;">package com.simplethread.test;
public class FirstThread extends Thread{
	private int i;
	//重写run()方法,run()方法体就是线程执行体
	public void run()
	{
		for(;i<10;i++)
		{
			//当线程继承Thread类时,直接使用this即可获取当前线程
			//Thread对象的getName()返回当前线程的名字
			//因此可以直接调用getName()方法返回当前线程的名字
			System.out.println(getName()+" "+i);
		}
	}
	public static void main(String[] args) {
		for(int i=0;i<5;i++)
		{
			//调用Thread的currentThread()方法获取当前线程
			System.out.println(Thread.currentThread().getName()+" "+i);
			if(i==2)
			{
				//创建并启动第一个线程
				new FirstThread().start();
				//创建并启动第二个线程
				new FirstThread().start();
			}			
		}
	}
}
</span>
2.实现Ruunable接口创建线程类

package com.simplethread.test;
public class SecondThread implements Runnable{
	private int i;
	//run()方法同样是线程执行体
	public void run()
	{
		for(;i<10;i++)
		{
			//当线程类实现Runnable接口时
			//如果想获取当前线程,只能用Thread.currentThread()方法
			System.out.println(Thread.currentThread().getName()					+" "+i);
		}
	}
	public static void main(String[] args) {
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()
					+" "+i);
			if(i==2)
			{
				SecondThread st=new SecondThread();
				//通过new Thread(target,name)方法创建新线程
				new Thread(st,"新线程1").start();
				new Thread(st,"新线程2").start();
			}
		}
	}
}

3.使用Callable和Future创建线程

package com.simplethread.test;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThirdThread {
	public static void main(String[] args) {		
		//先创建Callable对象
		ThirdThread rt=new ThirdThread();
		FutureTask<Integer> task=new FutureTask<Integer>( 
				new Callable<Integer>() {  
            public Integer call() { 
            	int i=0;
            	for(;i<10;i++)
            	{
            		System.out.println(Thread.currentThread().getName()
            				+"的循环变量i的值:"+i);
            	}
                return i;  
            }  
        });
		for(int i=0;i<10;i++)
		{
			System.out.println(Thread.currentThread().getName()
					+"的循环变量i的值:"+i);
			if(i==3)
			{
				//实质还是以Callable对象来创建并启动线程
				new Thread(task,"有返回值的线程").start();
			}
		}
		try
		{
			//获取线程返回值
			System.out.println("子线程返回值:"+task.get());
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
}
4.线程的生命周期

package com.simplethread.test;
public class InvokeRun extends Thread{
	private int i;
	//重写run()方法,run()方法的方法体就是线程执行体
	public void run()
	{
		for(;i<10;i++)
		{
			//直接调用run()方法时,Tread的this.getName()返回的是该对象的名字
			//而不是当前线程的名字
			//使用Thread.currentThread().getName()总是获取当前线程的名字
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}
	public static void main(String[] args) throws InterruptedException {
		for(int i=0;i<10;i++)
		{
			//调用Thread的currentThread()方法获取当前线程
			System.out.println(Thread.currentThread().getName()+" "+i);
			if(i==5)
			{
				//直接调用线程的run()方法
				//系统会把线程对象当成普通对象,把run()方法当成普通方法
				//所以下面两行代码并不会启动两个线程,而是依次执行两个run()方法
				new InvokeRun().run();
				new InvokeRun().run();
			}
		}
	}
}
5.线程死亡

package com.simplethread.test;
public class StartedDeadThread extends Thread{
	private int i;
	//重写run()方法,run()方法的方法体就是线程执行体
	public void run()
	{
		for(;i<10;i++)
		{
			System.out.println(getName()+" "+i);
		}
	}
	public static void main(String[] args) {
		//创建线程对象
		StartedDeadThread sd=new StartedDeadThread();
		for(int i=0;i<10;i++)
		{
			//调用Threade的currentThread()方法获取当前线程
			System.out.println(Thread.currentThread().getName()
					+" "+i);
			if(i==5)
			{
				//启动线程
				sd.start();
				//判断启动后台线程的isAlive()值,输出true
				System.out.println(sd.isAlive());
			}
			//当线程处于新建、死亡两种状态时,isAlive()方法返回false
			//当i>5时,该线程肯定已经启动过了,如果sd.isAlive()为假时
			//那就是死亡状态了
			if(i>5&&(sd.isAlive()))
			{
				//试图再次启动线程
				sd.start();
			}
		}
	}
}

6.控制线程

Join线程:

package com.simplethread.test;
public class JoinThread extends Thread{
	//提供一个有参数的构造器,用于设置该线程的名字
	public JoinThread(String name)
	{
		super(name);
	}
	//重写run()方法,定义线程执行体
	public void run()
	{
		for(int i=0;i<10;i++)
		{
			System.out.println(getName()+" "+i);			
		}
	}
	public static void main(String[] args) throws InterruptedException {
			//启动子线程
		new JoinThread("新线程").start();
		for(int i=0;i<10;i++)
		{
			if(i==2)
			{
				JoinThread jt=new JoinThread("被Join的线程:");
				jt.start();
				//main线程调用了jt线程的join()方法,main线程
				//必须等jt执行结束后向下执行
				jt.join();
			}
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}
}
7.后台线程

package com.simplethread.test;
public class DaemonThread extends Thread{
	//定义后台线程的线程执行体与普通线程没有任何区别
	public void run()
	{
		for(int i=0;i<10;i++)
		{
			System.out.println(getName()+" "+i);
		}
	}
	public static void main(String[] args) {
		DaemonThread t=new DaemonThread();
		//将此线程设置成后台线程
		t.setDaemon(true);
		t.start();
		//启动后台线程
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
		//------程序执行到此处,前台线程(main线程)结束-------
		//后台线程也应该随之结束
	}
}

8.线程睡眠:sleep

package com.simplethread.test;
import java.util.Date;
public class SleepTest {
	public static void main(String[] args) throws InterruptedException {
		for(int i=0;i<10;i++)
		{
			System.out.println("当前时间:"+new Date());
			//调用Sleep()方法让当前线程暂停1s
			Thread.sleep(2000);
		}

	}

}

9.线程让步:yield

package com.simplethread.test;
public class YieldTest extends Thread{
		public YieldTest(String name)
		{
			super(name);
		}
		//定义run()方法作为线程执行体
		public void run()
		{
			for(int i=0;i<10;i++)
			{
				System.out.println(getName()+" "+i);
				//当i=5时,使用yield()方法让当前线程让步
				if(i==5)
				{
					Thread.yield();
				}
			}
		}
	public static void main(String[] args) {
		//启动两个并发线程
		YieldTest yt1=new YieldTest("高级");
		//将yt1设置成最高优先级
		yt1.setPriority(Thread.MAX_PRIORITY);
		yt1.start();
		YieldTest yt2=new YieldTest("低级");
		//将yt2设置成最高优先级
		yt2.setPriority(Thread.MIN_PRIORITY);
		yt2.start();
	}
}

10.改变线程优先级

package com.simplethread.test;
public class PriorityTest extends Thread{
	//定义一个有参数的构造器,用于创建线程指定时指定name
	public PriorityTest(String name)
	{
		super(name);
	}
	public void run()
	{
		for(int i=0;i<10;i++)
		{
			System.out.println(getName()+",其优先级是: "
		+getPriority()+",循环变量的值为:"+i);
		}
	}
	public static void main(String[] args) {
		//改变线程的优先级
		Thread.currentThread().setPriority(6);
		for(int i=0;i<20;i++)
		{
			if(i==10)
			{
				PriorityTest low=new PriorityTest("低级");
				low.start();
				System.out.println("创建之初的优先级:"+
				low.getPriority());
				//设置改线程为最低优先级
				low.setPriority(Thread.MIN_PRIORITY);
			}
			if(i==15)
			{
				PriorityTest high=new PriorityTest("高级");
				high.start();
				System.out.println("创建之初的优先级:"+
				high.getPriority());
				//设置该线程为最高优先级
				high.setPriority(Thread.MAX_PRIORITY);
			}
		}
	}
}










































<think>我们根据用户的问题和提供的参考资料,详细讲解C++中std::thread的使用,包括线程创建、管理、同步机制等。 参考资料主要涉及[^1][^2][^3][^4],我们将结合这些内容进行讲解。 内容大纲: 1. 线程创建:使用函数指针、Lambda、函数对象、成员函数等 2. 线程管理:join和detach 3. 线程同步:互斥锁(std::mutex)和条件变量(std::condition_variable)等 4. 参数传递的注意事项 5. 线程局部存储(thread_local) 6. 异常处理 我们将按照上述结构详细展开,并给出代码示例。</think>### C++ `std::thread` 使用详解:线程创建与管理 C++11 引入的 `<thread>` 头文件提供了强大的多线程支持,其中 `std::thread` 是线程管理的核心类。以下是详细使用指南: --- #### 一、线程创建方式 线程可通过多种可调用对象创建: 1. **函数指针** ```cpp void task(int param) { std::cout << "线程执行: " << param << std::endl; } int main() { std::thread t(task, 42); // 创建线程并传递参数 t.join(); } ``` 2. **Lambda 表达式**(推荐) ```cpp std::thread t([](const std::string& msg) { std::cout << "Lambda线程: " << msg << std::endl; }, "Hello Thread"); ``` 3. **函数对象(Functor)** ```cpp struct Task { void operator()(int x) const { std::cout << "函数对象: " << x*x << std::endl; } }; std::thread t(Task{}, 5); // 传递函数对象实例 ``` 4. **类成员函数** ```cpp class Worker { public: void run(const std::string& data) { std::cout << "成员函数线程: " << data << std::endl; } }; Worker w; std::thread t(&Worker::run, &w, "Data"); // 需传递对象指针[^3] ``` --- #### 二、线程生命周期管理 1. **`join()`**:阻塞当前线程直到目标线程完成 ```cpp std::thread t([]{ /* 任务 */ }); t.join(); // 主线程在此等待 ``` 2. **`detach()`**:分离线程(后台运行,无法再控制) ```cpp std::thread t([]{ /* 长时间任务 */ }); t.detach(); // 主线程继续执行 ``` > ⚠️ 警告:未`join()`或`detach()`的线程析构时会调用`std::terminate()`[^2] 3. **`joinable()`**:检查线程是否可管理 ```cpp if (t.joinable()) { t.join(); // 安全操作 } ``` --- #### 三、线程同步机制 避免数据竞争需使用同步原语: 1. **互斥锁 (`std::mutex`)** ```cpp std::mutex mtx; int counter = 0; void safe_increment() { std::lock_guard<std::mutex> lock(mtx); // RAII自动解锁 ++counter; } ``` 2. **条件变量 (`std::condition_variable`)** 实现线程间通信: ```cpp std::condition_variable cv; std::mutex mtx; bool data_ready = false; // 生产者线程 void producer() { std::lock_guard<std::mutex> lock(mtx); data_ready = true; cv.notify_one(); // 通知消费者 } // 消费者线程 void consumer() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return data_ready; }); // 阻塞直到条件满足 } ``` --- #### 四、参数传递注意事项 1. **默认按值传递**:参数被复制到线程独立内存空间 ```cpp int x = 10; std::thread t([](int a){ a *= 2; }, x); // x值不变 ``` 2. **引用传递需用 `std::ref` 包装** ```cpp int y = 20; std::thread t([](int& b){ b *= 2; }, std::ref(y)); // y变为40 ``` 3. **移动语义优化大对象** ```cpp std::vector<int> big_data(1000); std::thread t([](std::vector<int>&& data){ // 使用移动后的数据 }, std::move(big_data)); // 转移所有权 ``` --- #### 五、线程局部存储 (`thread_local`) 创建线程私有变量: ```cpp thread_local int thread_id = 0; // 每个线程独立副本 void print_id() { std::cout << "线程ID: " << thread_id++ << std::endl; } int main() { std::thread t1(print_id); // 输出0 std::thread t2(print_id); // 输出0(非1) t1.join(); t2.join(); } ``` --- #### 六、异常处理 线程内异常需捕获处理,否则导致程序终止: ```cpp void risky_task() { try { throw std::runtime_error("线程内部错误"); } catch (const std::exception& e) { std::cerr << "捕获异常: " << e.what() << std::endl; } } ``` --- ### 最佳实践 1. 优先使用 RAII 包装器(如 `std::lock_guard`) 2. 避免全局变量,使用参数传递数据 3. 用 `std::async` 替代 `std::thread` 实现任务并行(简化资源管理)[^4] 4. C++20 推荐 `std::jthread`(自动管理生命周期) ```cpp // std::async 示例 auto future = std::async(std::launch::async, []{ return std::sqrt(2.0); // 异步计算 }); double result = future.get(); // 获取结果 ``` --- ### 相关问题 1. 如何实现线程池以提高大量小任务的性能? 2. `std::atomic` 在无锁编程中如何应用? 3. 多线程调试有哪些常用工具和技巧? 4. C++20 协程如何简化异步编程模型? > 源码示例在 GCC/Clang 需编译选项:`-std=c++11 -pthread` > MSVC 需启用:`/std:c++latest /EHsc` [^1]: 线程创建方式与参数传递机制 [^2]: 线程生命周期管理关键点 [^3]: 类成员函数线程化实现 [^4]: 高级异步任务处理方案
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值