进程:进程包含一个程序运行所需要的资源,进程即是一个程序,一个进程可以有多个线程。
线程:操作系统能够进行运算调度的最小单位。
Windows 任务管理器
进程可以有多个线程。
UnStarted 处于创建但未启动状态
Runnable 调用了start,处于可运行或准备运行状态
Running 运行中状态
Not Runable 非运行状态,调用了sleep、wait或I/O被阻塞
Dead 任务完成后,处于死亡或终止状态
Thread 常用属性
class Program
{
static void Main(string[] args)
{
Console.WriteLine("主线程:"+Thread.CurrentThread.ManagedThreadId);
Thread t = new Thread(new ThreadStart(Thread_A));
Console.WriteLine("创建线程 -- 线程状态:"+t.ThreadState);
t.Start();
Thread.Sleep(1000); // 睡眠1秒
Console.ReadKey();
}
private static void Thread_A()
{
Console.WriteLine("常用属性值:");
Console.WriteLine("当前运行线程实例:"+ Thread.CurrentThread);
Console.WriteLine("当前线程唯一ID:"+Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("当前线程名称:"+Thread.CurrentThread.Name);
Console.WriteLine("当前线程优先级:"+Thread.CurrentThread.Priority);
Console.WriteLine("当前线程状态:"+Thread.CurrentThread.ThreadState);
Console.WriteLine("当前线程是否处于活跃:"+Thread.CurrentThread.IsAlive);
Console.WriteLine("当前线程是否为后台线程:"+Thread.CurrentThread.IsBackground);
/*
前台线程:主程序必须等待线程执行完毕后才能退出程序
后台线程:主程序执行完毕后就退出,不管线程是否完成
*/
}
}
输出
Thread 优先级
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(A));
t1.Start();
Thread t2 = new Thread(new ThreadStart(B));
t2.Start();
Thread t3 = new Thread(new ThreadStart(C));
t3.Start();
Console.ReadKey();
}
private static void A()
{
Console.WriteLine("A");
}
private static void B()
{
Console.WriteLine("B");
}
private static void C()
{
Console.WriteLine("C");
}
}
第一次输出:ABC
第二次输出:BAC
第三次输出:ABC
第四次输出:ACB
第四次输出
Thread 优先级相同时没有先后顺序,设置优先级:
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(A));
t1.Start();
t1.Priority = ThreadPriority.Highest;
Thread t2 = new Thread(new ThreadStart(B));
t2.Start();
t2.Priority = ThreadPriority.Highest;
Thread t3 = new Thread(new ThreadStart(C));
t3.Start();
t3.Priority = ThreadPriority.Highest;
Thread t4 = new Thread(new ThreadStart(D));
t4.Start();
Console.ReadKey();
}
private static void A()
{
Console.WriteLine("A");
}
private static void B()
{
Console.WriteLine("B");
}
private static void C()
{
Console.WriteLine("C");
}
private static void D()
{
Console.WriteLine("D");
}
}
第一次输出:CABD
第二次输出:ABCD
第三次输出:ACBD
第四次输出:ACBD
D的优先级最低,ABC优先级都是 Highest,同优先级不分顺序
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main,标识:"+Thread.CurrentThread.ManagedThreadId);
Thread t1 = new Thread(new ParameterizedThreadStart(A)); // 带参数的方法
t1.Start("ThreadTest"); // 传参
Console.WriteLine("Main,标识:"+Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
private static void A(object data)
{
Console.WriteLine("Message: "+data+",标识:"+Thread.CurrentThread.ManagedThreadId);
}
}
输出
Thread.Join() 可以阻塞主线程
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(() => { Console.WriteLine("A"); });
t1.Start();
t1.Join();
Console.WriteLine("主线程");
Console.Read();
}
}
输出
阻塞所有线程,t1 执行完成之后再执行其他线程
Thread.Sleep(); 阻塞当前线程
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(() =>
{
Console.WriteLine("A");
Thread.Sleep(1000);
});
t1.Start();
Console.WriteLine("主线程");
Console.Read();
}
}
输出
当前线程阻塞1s,Thread.Sleep() 单位是ms
来源:https://www.lidihuo.com/csharp/csharp-thread-class.html
例:A、B同时在银行取钱,余额只有1000,两人都需要取1000,A取出来1000后,B取得时候提示余额不足
class Program
{
private static object obj = new object();
private static int money = 1000;
static void Main(string[] args)
{
Thread thread1 = new Thread(Sum1);
thread1.Start();
Thread thread2 = new Thread(Sum1);
thread2.Start();
Console.ReadKey();
}
public static void Sum1()
{
lock (obj)
{
if(money >= 1000)
{
money -= 1000;
Console.WriteLine("余额:{0}",money);
}
else
{
Console.WriteLine("余额不足");
}
}
}
}
输出
ThreadPool 线程池是为了方便对线程进行管理,线程池可以限制线程数量且可以重复使用
static void Main(string[] args)
{
Console.WriteLine("Main,标识:"+Thread.CurrentThread.ManagedThreadId);
ThreadPool.QueueUserWorkItem(p => A("")); // A括号里面传参数
ThreadPool.QueueUserWorkItem(new WaitCallback(A));
Console.WriteLine("Main,标识:"+Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
private static void A(object data)
{
Console.WriteLine("Message: "+data+",标识:"+Thread.CurrentThread.ManagedThreadId);
}
输出
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main,标识:"+Thread.CurrentThread.ManagedThreadId);
Thread t1 = new Thread(new ThreadStart(A));
Thread t2 = new Thread(new ThreadStart(B));
t1.Start();
t2.Start();
Console.WriteLine("Main,标识:"+Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
private static void B()
{
Console.WriteLine("Thread B");
}
private static void A()
{
Console.WriteLine("Thread A");
}
}
输出
两端代码运行过多次,Thread 主线程会等待线程,ThreadPool 主线程不会等待线程
线程数量
class Program
{
static void Main(string[] args)
{
int workerThreads; // 工作线程
int completionPortThreads; // I/O 线程
ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
Console.WriteLine(#34;最大线程数:{workerThreads},{completionPortThreads}");
ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
Console.WriteLine(#34;最小线程数:{workerThreads},{completionPortThreads}");
Console.ReadLine();
}
}
输出
设置数量
class Program
{
static void Main(string[] args)
{
int workerThreads; // 工作线程
int completionPortThreads; // I/O 线程
// 设置最大线程
ThreadPool.SetMaxThreads(5, 5);
// 设置最小线程
ThreadPool.SetMinThreads(1, 1);
ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
Console.WriteLine(#34;最大线程数:{workerThreads},{completionPortThreads}");
ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
Console.WriteLine(#34;最小线程数:{workerThreads},{completionPortThreads}");
Console.ReadLine();
}
}
输出
线程重用
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
Console.ReadKey();
}
private static void GetMoney(object state)
{
Console.WriteLine("线程标识: "+Thread.CurrentThread.ManagedThreadId);
}
}
输出
从输出的线程标识中可以看出只用了三个线程,减少了线程的创建
class Program
{
static void Main(string[] args)
{
string msg = "The User Does't exit";
object mg = "Hello Banananana";
ThreadPool.QueueUserWorkItem((a) => Message(msg));
ThreadPool.QueueUserWorkItem(new WaitCallback(Message), mg); // 传参类型需要 Object
Console.Read();
}
private static void Message(string msg)
{
Console.WriteLine(msg);
}
private static void Message(object msg)
{
Console.WriteLine(msg+"");
}
}
输出
QueueUserWorkItem
回调方法
ThreadPool 不能控制线程执行的顺序,也不能获取线程池内线程的取消、异常、完成的通知
class Program
{
static void Main(string[] args)
{
Console.WriteLine("开始执行");
var factory = new TaskFactory();
Task t1 = factory.StartNew(() => Console.WriteLine("A,标识: {0}",Thread.CurrentThread.ManagedThreadId));
Task t2 = Task.Factory.StartNew(() => Console.WriteLine("B,标识: {0}",Thread.CurrentThread.ManagedThreadId));
Task t3 = new Task(() => Console.WriteLine("C,标识: {0}",Thread.CurrentThread.ManagedThreadId));
t3.Start();
Task t4 = Task.Run(() => Console.WriteLine("D,标识: {0}",Thread.CurrentThread.ManagedThreadId));
Console.Read();
}
}
输出
class Program
{
static void Main(string[] args)
{
Task t1 = new Task(() => { return #34;A, 标识:{Thread.CurrentThread.ManagedThreadId}"; });
t1.Start();
Task t2 = Task.Factory.StartNew(() => { return #34;B, 标识:{Thread.CurrentThread.ManagedThreadId}"; });
Task t3 = Task.Run(() => { return #34;C, 标识:{Thread.CurrentThread.ManagedThreadId}"; });
Console.WriteLine(t1.Result);
Console.WriteLine(t2.Result);
Console.WriteLine(t3.Result);
Console.Read();
}
}
输出
注:Task.Result 返回结果时会阻塞线程
class Program
{
static void Main(string[] args)
{
Task t1 = new Task(() => Console.WriteLine("Task 线程"));
t1.RunSynchronously(); // 同步方法
Console.WriteLine("主线程");
Console.Read();
}
}
输出
Thread 也有方法可以进行阻塞,但每次只能对一个线程进行阻塞,Task 可以有方法可以解决这个问题,task.Wait() 等待 task 执行完成,类似 Thread.Join(),Task.WaitAll() 执行完所有 task 再解除线程,Task.WaitAny() 只要有一个 task 执行完成就解除线程
Task.Wait
class Program
{
static void Main(string[] args)
{
Task t1 = new Task(() => { Console.WriteLine("A"); });
t1.Start();
t1.Wait();
Console.WriteLine("主线程");
Console.Read();
}
}
Task.Wait()
阻塞所有线程,等待当前执行完成
Task.WaitAll
class Program
{
static void Main(string[] args)
{
List list = new List();
Task t1 = Task.Run(() => Console.WriteLine("A"));
Task t2 = Task.Run(() => Console.WriteLine("B"));
Task t3 = Task.Run(() => Console.WriteLine("C"));
Task t4 = Task.Run(() => Console.WriteLine("D"));
list.Add(t1);
list.Add(t2);
list.Add(t3);
list.Add(t4);
Task.WaitAll(list.ToArray());
Console.WriteLine("主线程");
Console.Read();
}
}
Task.WaitAll
等待 Task线程组 完成
Task.WaitAny
class Program
{
static void Main(string[] args)
{
List list = new List();
Task t1 = Task.Run(() => Console.WriteLine("A"));
Task t2 = Task.Run(() => Console.WriteLine("B"));
Task t3 = Task.Run(() => Console.WriteLine("C"));
Task t4 = Task.Run(() => Console.WriteLine("D"));
list.Add(t1);
list.Add(t2);
list.Add(t3);
list.Add(t4);
Task.WaitAny(list.ToArray());
Console.WriteLine("主线程");
Console.Read();
}
}
Task.WaitAny
线程组任意线程完成就接触阻塞
有一个需求,需要在 task 线程组 执行完成之后执行
class Program
{
static void Main(string[] args)
{
List list = new List();
Task t1 = Task.Run(() => Console.WriteLine("A"));
Task t2 = Task.Run(() => Console.WriteLine("B"));
Task t3 = Task.Run(() => Console.WriteLine("C"));
Task t4 = Task.Run(() => Console.WriteLine("D"));
list.Add(t1);
list.Add(t2);
list.Add(t3);
list.Add(t4);
// 二选一即可
Task.WhenAll(list.ToArray()).ContinueWith(t => Console.WriteLine("执行完成"));
// Task.Factory.ContinueWhenAll(list.ToArray(), t => Console.WriteLine("执行完成"));
Console.WriteLine("主线程");
Console.Read();
}
}
输出
从输出中可以看出,task 不会阻塞主线程
有一个需求,需要在 task 线程任意线程执行完成之后执行
class Program
{
static void Main(string[] args)
{
List list = new List();
Task t1 = Task.Run(() => Console.WriteLine("A"));
Task t2 = Task.Run(() => Console.WriteLine("B"));
Task t3 = Task.Run(() => Console.WriteLine("C"));
Task t4 = Task.Run(() => Console.WriteLine("D"));
list.Add(t1);
list.Add(t2);
list.Add(t3);
list.Add(t4);
// 二选一即可
Task.WhenAny(list.ToArray()).ContinueWith(t => Console.WriteLine("执行完成"));
// Task.Factory.ContinueWhenAny(list.ToArray(), t => Console.WriteLine("执行完成"));
Console.WriteLine("主线程");
Console.Read();
}
}
输出
这个方法也不会阻塞主线程
有一个下载任务已运行,但这个文件已经不需要了,需要取消这个下载任务
class Program
{
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
int i;
Task t1 = new Task(() =>
{
i = 0;
while (!cts.IsCancellationRequested)
{
Thread.Sleep(1000);
Console.WriteLine(#34;下载中:{i++}%");
if(cts.IsCancellationRequested)
Console.WriteLine("下载已取消");
}
});
t1.Start();
// cts.Cancel(); // 立刻取消
cts.CancelAfter(1000 * 10); // 10秒后取消
Console.Read();
}
}
输出
除了使用 if 语句输出 下载已取消,CancellationTokenSource 也有一个自带的注册任务取消事件
class Program
{
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
int i;
Task t1 = new Task(() =>
{
i = 0;
while (!cts.IsCancellationRequested)
{
Thread.Sleep(1000);
Console.WriteLine(#34;下载中:{i++}%");
}
});
// 取消后执行
cts.Token.Register(() =>
{
Console.WriteLine("下载已取消");
});
t1.Start();
cts.CancelAfter(1000 * 10);
Console.Read();
}
}
输出
class Program
{
static void Main(string[] args)
{
Console.WriteLine(GetContentAsync().Result);
Console.Read();
}
// 不会阻塞线程
async static Task GetContentAsync()
{
Encoding GB2312 = Encoding.GetEncoding("GB2312");
Encoding GBK = Encoding.GetEncoding("GBK");
FileStream fs = new FileStream(@"D:\1.txt", FileMode.Open);
byte[] bytes = new byte[fs.Length];
Console.WriteLine("开始读取文件");
int len = await fs.ReadAsync(bytes,0,bytes.Length);
string res = Encoding.UTF8.GetString(bytes);
return res;
}
}
输出
Task 对ThreadPool做了封装,主要是为了更好地控制线程池中的线程
完!坚持and放弃,我选择坚持
留言与评论(共有 0 条评论) “” |