1.线程优先级
通过过设置属性Priority
class ThreadSample
{
private bool _isStop = false;
public void Stop()
{
_isStop = true;
}
public void CountNumbers()
{
long counter = 0;
while(!_isStop)
{
counter++;
}
Console.WriteLine($"{Thread.CurrentThread.Name} with {Thread.CurrentThread.Priority,11} "+
$"priority has a count:{counter,13:N0}");
}
}
static void RunThreads()
{
var sample = new ThreadSample();
var oneTh = new Thread(sample.CountNumbers);
oneTh.Name = "thread one";
var twoTh = new Thread(sample.CountNumbers);
twoTh.Name = "thread two";
oneTh.Priority = ThreadPriority.Highest;//最高优先级
twoTh.Priority = ThreadPriority.Lowest;//最低优先级
oneTh.Start();
twoTh.Start();
Thread.Sleep(2000);
sample.Stop();
}
//线程优先级
Console.WriteLine($"Current thread priority:{Thread.CurrentThread.Priority}");
Console.WriteLine("Running on all cores available");
RunThreads();
Thread.Sleep(2000);
Console.WriteLine( "Running on a single core");
GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
RunThreads();
输出:
使用计算机上的可用核,在2秒内得到初步结果,最高优先级的线程通常会计算更多的迭代,但是2个结果接近。
模拟在一个核上运行,结果完全不同了,CPU核大部分时间运行高优先级的线程,只留很少的时间运行低优先级的线程
2. 前台线程和后台线程
class ThreadSample2
{
private readonly int _iterations;
public ThreadSample2(int iteratios)
{
_iterations = iteratios;
}
public void CountNumbers()
{
for (int i = 0; i < _iterations; i++)
{
Thread.Sleep(500);
Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
}
}
}
//前台线程和后台线程
var foreSample = new ThreadSample2(10);
var backSample= new ThreadSample2(20);
var oneTh = new Thread(foreSample.CountNumbers);
oneTh.Name = "Forground Thread";
var twoTh = new Thread(backSample.CountNumbers);
twoTh.Name = "Background Thread";
twoTh.IsBackground = true;
oneTh.Start();
twoTh.Start();
输出:
通过设置属性 IsBackground来设置后台线程,默认显示创建的线程都是前台线程。进程会等待前台线程完成后再结束工作,但是如果只剩下后台进程则会直接结束工作。
3.向线程传递参数
static void Count(object iterations)
{
CounterNmbers((int)iterations);
}
private static void CounterNmbers(int iterations)
{
for (int i = 0; i <=iterations; i++)
{
Thread.Sleep(500);
Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
}
}
static void PrintNumber(int number)
{
Console.WriteLine(number);
}
class Threadsample
{
private readonly int _iterations;
public Threadsample(int iterations)
{
_iterations = iterations;
}
public void CountNumbers()
{
for (int i = 0; i <=_iterations; i++)
{
Thread.Sleep(500);
Console.WriteLine($"{Thread.CurrentThread.Name} print{i}");
}
}
}
测试代码:
var sample = new Threadsample(10);
var t1 = new Thread(sample.CountNumbers);
t1.Name = "Thread_1";
t1.Start();
t1.Join();
Console.WriteLine("----------------------------");
//通过实例化类的构造函数传入参数值 10,创建新的线程,传入实例方法。
var t2 = new Thread(Count);
t2.Name = "Thread_2";
t2.Start(8);
t2.Join();
Console.WriteLine("----------------------------");
//start( ) 方法接收一个object类型的单个参数,8传给Count对象,被转换为整形。
var t3 = new Thread(() => CounterNmbers(12));
t3.Name = "Thread_3";
t3.Start();
t3.Join();
Console.WriteLine("----------------------------");
// 使用Lambda表达式,传递数字12,
int i = 10;
var t4 = new Thread(() => PrintNumber(i));
i = 20;
var t5 = new Thread(() => PrintNumber(i));
t4.Start();
t5.Start();
// lambda表达式中使用相同变量,共享变量,导致这个2个线程启动之前变量被修改为20
输出:
4. 使用Lock关键字
确保当一个线程使用某些资源时其它线程无法使用该资源。
abstract class CounterBase
{
public abstract void Increment();
public abstract void Decrement();
}
class Counter : CounterBase
{
public int Count { get; private set; }
public override void Decrement()
{
Count--;
}
public override void Increment()
{
Count++;
}
}
class CounterWithLock : CounterBase
{
private readonly object _syncRoot = new object();
public int Count { get; private set; }
public override void Decrement()
{
lock (_syncRoot)
{
Count--;
}
}
public override void Increment()
{
lock (_syncRoot)
{
Count++;
}
}
}
static void TestCounter(CounterBase c)
{
for (int i = 0; i < 100000; i++)
{
c.Increment();
c.Decrement();
}
}
测试代码:
Console.WriteLine("Unlock......");
var c = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c));
var t3 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c.Count}");
Console.WriteLine("=================================");
//启动3个线程共享变量,导致结果不确定,可能是0但大多数情况不为0
//Counter类不是线程安全的,存在竞争条件多线程环境中常见导致错误的原因
Console.WriteLine("Lock......");
var cl = new CounterWithLock();
t1 = new Thread(() => TestCounter(cl));
t2 = new Thread(() => TestCounter(cl));
t3 = new Thread(() => TestCounter(cl));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{cl.Count}");
//lock关键字 锁定一个对象,需要访问该对象的其它线程则处于锁定状态,直到该对象解除
输出