标签:负载 lam 模型 sys 输出内容 其它 对象 安全 reading
什么是线程Thread
例子:
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(WriteY); //开启一个新的线程 Thread
thread.Name = "Y Thread...";
thread.Start();
for (int i = 0; i < 1000; i++)
Console.WriteLine("x");
Console.ReadKey();
}
private static void WriteY()
{
for(int i = 0; i < 1000; i++)
{
Console.WriteLine("y");
}
}
}
调用Join方法,就可以等待另一个线程结束。
例子:
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
t.Start();
t.Join();//当前线程会等待t线程执行结束
Console.WriteLine("线程结束");
Console.Read();
}
private static void WriteY()
{
for(int i = 0; i < 1000; i++)
{
Console.Write("y");
}
}
}
class Program
{
static Thread thread1, thread2;
static void Main(string[] args)
{
thread1 = new Thread(ThreadProc);
thread1.Name = nameof(thread1);
thread1.Start();
thread2 = new Thread(ThreadProc);
thread2.Name = nameof(thread2);
thread2.Start();
Console.Read();
}
private static void ThreadProc()
{
Console.WriteLine($"\nCurrent Thread:{Thread.CurrentThread.Name}");
if (Thread.CurrentThread.Name == nameof(thread1) &&
thread2.ThreadState != ThreadState.Unstarted)
thread2.Join();
Thread.Sleep(4000);
Console.WriteLine($"\nCurrent thread:{Thread.CurrentThread.Name}");
Console.WriteLine($"Thread1:{thread1.ThreadState}");
Console.WriteLine($"Thread2:{thread2.ThreadState}");
}
}
输出内容:
Current Thread:thread1
Current Thread:thread2
Current thread:thread2
Thread1:WaitSleepJoin
Thread2:Running
Current thread:thread1
Thread1:Running
Thread2:Stopped
例子:
class Program
{
static Thread thread1, thread2;
static void Main(string[] args)
{
thread1 = new Thread(ThreadProc);
thread1.Name = nameof(thread1);
thread1.Start();
thread2 = new Thread(ThreadProc);
thread2.Name = nameof(thread2);
thread2.Start();
Console.Read();
}
private static void ThreadProc()
{
Console.WriteLine($"\nCurrent Thread:{Thread.CurrentThread.Name}");
if (Thread.CurrentThread.Name == nameof(thread1) &&
thread2.ThreadState != ThreadState.Unstarted)
if (thread2.Join(2000))
Console.WriteLine("线程2结束");
else
Console.WriteLine("线程2超时了");
Thread.Sleep(4000);
Console.WriteLine($"\nCurrent thread:{Thread.CurrentThread.Name}");
Console.WriteLine($"Thread1:{thread1.ThreadState}");
Console.WriteLine($"Thread2:{thread2.ThreadState}");
}
}
输出:
Current Thread:thread1
Current Thread:thread2
线程2超时了
Current thread:thread2
Thread1:WaitSleepJoin
Thread2:Running
Current thread:thread1
Thread1:Running
Thread2:Stopped
Thread.Sleep()方法会暂停当前的线程,并等待一段时间。
注意:
Sleep(0)或Yield有时在高级性能调试的生产代码中很有用。它也是一个很好的诊断工具,有助于发现线程安全问题:
如果在代码中的任何地方插入Thread.Yield()就破坏了程序,那么你的程序几乎肯定有bug。
如果线程的执行由于某种原因导致暂停,那么就认为该线程被阻塞了。
被阻塞的线程会立即将其处理器的时间片生成给其它线程,从此就不再消耗处理器时间,直到满足其阻塞条件为止。
可以通过ThreadState这个属性来判断线程是否处于被阻塞的状态:
bool blocked = (thread.ThreadState & ThreadState.WaitSleepJoin) != 0;
ThreadState是一个flags enum,通过按位的形式,可以合并数据的选项。
//
// 摘要:
// 指定 System.Threading.Thread 的执行状态。
[ComVisible(true)]
[Flags]
public enum ThreadState
{
//
// 摘要:
// 线程已启动且尚未停止。
Running = 0,
//
// 摘要:
// 正在请求线程停止。 这仅用于内部。
StopRequested = 1,
//
// 摘要:
// 正在请求线程挂起。
SuspendRequested = 2,
//
// 摘要:
// 线程正作为后台线程执行(相对于前台线程而言)。 此状态可以通过设置 System.Threading.Thread.IsBackground 属性来控制。
Background = 4,
//
// 摘要:
// 尚未对线程调用 System.Threading.Thread.Start 方法。
Unstarted = 8,
//
// 摘要:
// 线程已停止。
Stopped = 16,
//
// 摘要:
// 线程已被阻止。 这可能是调用 System.Threading.Thread.Sleep(System.Int32) 或 System.Threading.Thread.Join、请求锁定(例如通过调用
// System.Threading.Monitor.Enter(System.Object) 或 System.Threading.Monitor.Wait(System.Object,System.Int32,System.Boolean))或在线程同步对象上(例如
// System.Threading.ManualResetEvent)等待的结果。
WaitSleepJoin = 32,
//
// 摘要:
// 线程已挂起。
Suspended = 64,
//
// 摘要:
// 已对线程调用了 System.Threading.Thread.Abort(System.Object) 方法,但线程尚未收到试图终止它的挂起的 System.Threading.ThreadAbortException。
AbortRequested = 128,
//
// 摘要:
// 线程状态包括 System.Threading.ThreadState.AbortRequested 并且该线程现在已死,但其状态尚未更改为 System.Threading.ThreadState.Stopped。
Aborted = 256
}
Blocking vs Spinning
IO-bound操作的工作方式有两种:
同步等待的I/O-bound操作将大部分时间花在阻塞线程上。
它们也可以周期性的在一个循环里进行“打转(自旋)”
while(DateTime.Now < nextStartTime);
在忙等待和阻塞方面有一些细微差别。
在C#3.0之前,没有lambda表达式。可以使用Thread的Start方法来传递参数。
Thread的重载构造函数可以接受下列两个委托之一作为参数:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
提升线程优先级的时候需特别注意,因为它可能“饿死”其它线程。
如果想让某线程(Thread)的优先级比其它进程(Process)中的线程(Thread)高,那就必须提升进程(Process)的优先级。
使用System.Diagnostics下的Process类。
using (Process p = Process.GetCurrentProcess())
{
p.PriorityClass = ProcessPriorityClass.High;
}
这可以很好地用于只做少量工作且需要较低延迟的非UI进程。
对于需要大量计算的应用程序(尤其是有UI的应用程序),提高进程优先级可能会使其它进程饿死,从而降低整个计算机的速度。
Task.Run
默认情况下,CLR在线程池中运行Task,这非常适合短时间运行的Compute-Bound类工作。
针对长时间运行的任务或者阻塞操作,你可以不采用线程池。
Task task = Task.Factory.StartNew(() => { }, TaskCreationOptions.LongRunning);
如果同时运行多个long-running tasks(尤其是其中有处于阻塞状态的),那么性能将会受很大影响,这时有比TaskCreationOptions.LongRunning更好的办法:
标签:负载 lam 模型 sys 输出内容 其它 对象 安全 reading
原文地址:https://www.cnblogs.com/zzr-stdio/p/13283056.html