什么是多线程?
- 定义:多线程允许一个程序分成多个独立的执行路径来进行并发操作。
- 用途:提高程序的执行效率,特别是在I/O操作、计算密集型任务和用户交互中。
多线程核心概念
1. 创建和管理线程
- 使用 Thread 类
cs
using System;
using System.Threading;
public class Program
{
public static void Main()
{
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Main thread: " + i);
Thread.Sleep(100);
}
thread.Join(); // 等待新线程完成
}
public static void DoWork()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Worker thread: " + i);
Thread.Sleep(100);
}
}
}
2. 线程池
- 使用 ThreadPool 线程池可以有效地管理和复用线程资源。
cs
using System;
using System.Threading;
public class Program
{
public static void Main()
{
ThreadPool.QueueUserWorkItem(DoWork);
Console.WriteLine("Main thread does some work, then sleeps.");
Thread.Sleep(1000);
Console.WriteLine("Main thread exits.");
}
public static void DoWork(object state)
{
Console.WriteLine("Worker thread is processing the task.");
}
}
3. 使用任务并行库 (TPL)
- 使用 Task 和 Task<T> 任务并行库提供了更高层次的抽象来处理异步编程。
cs
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
Task workTask = DoWorkAsync();
Console.WriteLine("Main thread continues to run.");
await workTask; // 等待异步任务完成
}
public static async Task DoWorkAsync()
{
await Task.Delay(1000); // 模拟异步工作
Console.WriteLine("Async task has completed.");
}
}
高级主题
线程间同步
- 使用锁 (lock) 防止数据竞争
cs
public class Counter
{
private int count = 0;
private readonly object lockObj = new object();
public void Increment()
{
lock (lockObj)
{
count++;
}
}
}
并发集合
- .NET提供了一些线程安全的集合类,如ConcurrentDictionary、BlockingCollection等。
cs
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
public class ConcurrentExample
{
public static void Main()
{
var concurrentBag = new ConcurrentBag<int>();
Parallel.For(0, 10, i =>
{
concurrentBag.Add(i);
});
foreach (var item in concurrentBag)
{
Console.WriteLine(item);
}
}
}
使用场景
1.I/O密集型操作:
- 多线程可以提高文件读写或网络请求的吞吐量。
2.后台任务:
- 在不影响主线程响应的情况下执行长时间运行的计算或更新。
3.用户界面:
- 使用多线程可防止UI卡顿,保持应用程序响应性。
实践习题
cs
using System;
using System.Threading;
public class Program
{
private static readonly object lockObj = new object();
private static int counter = 0;
private const int maxCount = 10;
public static void Main()
{
Thread evenThread = new Thread(PrintEven);
Thread oddThread = new Thread(PrintOdd);
evenThread.Start();
oddThread.Start();
evenThread.Join();
oddThread.Join();
}
public static void PrintEven()
{
while (true)
{
lock (lockObj)
{
if (counter >= maxCount)
break;
if (counter % 2 == 0)
{
Console.WriteLine("Even: " + counter);
counter++;
}
}
}
}
public static void PrintOdd()
{
while (true)
{
lock (lockObj)
{
if (counter >= maxCount)
break;
if (counter % 2 != 0)
{
Console.WriteLine("Odd: " + counter);
counter++;
}
}
}
}
}
说明:
- 使用一个公共的整数counter来记录当前数字。
- 两个线程PrintEven和PrintOdd分别负责打印偶数和奇数。
- 使用lock关键字确保对counter的访问是线程安全的。
2.实现一个程序,通过Task启动多个异步下载模拟任务,并在全部完成后输出结果。
cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
List<Task<string>> downloadTasks = new List<Task<string>>();
// 模拟三个下载任务
downloadTasks.Add(SimulateDownloadAsync("File1"));
downloadTasks.Add(SimulateDownloadAsync("File2"));
downloadTasks.Add(SimulateDownloadAsync("File3"));
string[] results = await Task.WhenAll(downloadTasks);
foreach (string result in results)
{
Console.WriteLine(result);
}
}
public static async Task<string> SimulateDownloadAsync(string fileName)
{
// 模拟下载延迟
await Task.Delay(new Random().Next(500, 2000));
return $"{fileName} downloaded.";
}
}
说明:
- 使用Task启动多个异步下载任务。
- SimulateDownloadAsync方法模拟下载过程,返回任务完成后的消息。
- Task.WhenAll用于等待所有下载任务完成,并收集每个任务的结果。
这些例子展示了如何使用多线程和任务并行库来管理并发操作,提高程序效率。如果有任何问题或需要进一步讲解,请随时告诉我!