在控制台中,因为线程随机 sleep ,它将显示线程的顺序
3,2,1或1,2,3或...
我怎样才能有固定的订单?
为什么设置优先级不会影响代码?
//ThreadTester.cs
//以不同的时间间隔打印多线程。
using System;
using System.Threading;
namespace threadTester
{
// class ThreadTester demonstrates basic threading concepts
class ThreadTester
{
static void Main(string[] args)
{
// Create and name each thread. Use MessagePrinter's
// Print method as argument to ThreadStart delegate.
MessagePrinter printer1 = new MessagePrinter();
Thread thread1 =
new Thread(new ThreadStart(printer1.Print));
thread1.Name = "thread1";
MessagePrinter printer2 = new MessagePrinter();
Thread thread2 =
new Thread(new ThreadStart(printer2.Print));
thread2.Name = "thread2";
MessagePrinter printer3 = new MessagePrinter();
Thread thread3 =
new Thread(new ThreadStart(printer3.Print));
thread3.Name = "thread3";
Console.WriteLine("Starting threads");
// call each thread's Start method to place each
// thread in Started state
thread1.Priority = ThreadPriority.Lowest;
thread2.Priority = ThreadPriority.Normal;
thread3.Priority = ThreadPriority.Highest;
thread1.Start();
thread2.Start();
thread3.Start();
Console.WriteLine("Threads started\n");
Console.ReadLine();
} // end method Main
} // end class ThreadTester
// Print method of this class used to control threads
class MessagePrinter
{
private int sleepTime;
private static Random random = new Random();
// constructor to initialize a MessagePrinter object
public MessagePrinter()
{
// pick random sleep time between 0 and 5 seconds
sleepTime = random.Next(5001);
}
// method Print controls thread that prints messages
public void Print()
{
// obtain reference to currently executing thread
Thread current = Thread.CurrentThread;
// put thread to sleep for sleepTime amount of time
Console.WriteLine(
current.Name + " going to sleep for " + sleepTime);
Thread.Sleep(sleepTime);
// print thread name
Console.WriteLine(current.Name + " done sleeping");
} // end method Print
} // end class MessagePrinter
}
最佳答案
您之所以使用线程正是因为您不关心事情按特定顺序发生,而是想要:
在每种情况下,您都不必关心自己什么时候会发生什么。
然而:
为了获得理想的性能,每个时刻都应该在每个内核上运行一个线程(或者在超线程内核上可能运行两个线程,但这会带来更多的复杂性)。假设您有一台具有4个核心和8个任务的计算机。
如果任务涉及大量等待I/O的任务,那么将启动四个任务,每个任务都将达到等待该I/O的地步,并允许其他任务之一取得一些进展。很有可能即使任务数是内核数的两倍,它最终仍将有大量空闲时间。如果每个任务要花费20秒,那么在不同的线程上执行它们可能会使它们都在20秒多一点的时间内完成,因为所有这些都花了20秒的大部分时间在等待其他事情。
如果您正在执行使CPU一直忙碌的任务(没有太多等待内存,当然也没有I/O),那么您一次可以执行四个这样的任务,而其他任务正在等待它们要么结束,要么放弃自己的时间。在这里,如果每一个都花费20秒,那么您最好的总时间就是大约40秒(并且假设系统上任何进程的其他线程都不需要CPU,那么您在设置CPU时就完全没有开销了)线程等)。
如果有更多的工作要做( Activity 工作要做,而不是等待I/O完成,另一个线程释放锁,等等),而不是内核,则OS调度程序将在不同线程之间进行交换。积极点。确切的细节因操作系统而异(不同的Windows版本,包括台式机和服务器设置之间的一些重要差异,采用不同的方法,不同的Linux版本以及从2.4到2.6的特别大的更改以及不同的Unix等)都具有不同的策略)。
他们共有的一件事是确保完成任务的共同目标。
线程优先级和进程优先级是影响此调度的方式。使用Windows,每当有更多线程在等待工作而不是核心在工作时,那些优先级最高的线程将以循环方式获得给定的CPU时间。如果没有该优先级的线程,那么将给倒数第二个线程分配CPU时间,然后分配下一个,依此类推。
这是使事情停滞不前的好方法。当一个被赋予高优先级的线程(大概是因为它的工作被认为是至关重要的)正在等待一个被赋予低优先级的线程(可能是因为它的工作被认为不那么重要,并且人们希望它总是将时间浪费在线程上)时,这可能会导致复杂化。其他优先级),并且低优先级线程不会一直被分配CPU时间,因为总是有比可用内核更高优先级的线程。因此,所谓的高优先级线程根本没有CPU时间。
为了解决这种情况,Windows有时会提升长时间未运行的线程。这可以解决问题,但是现在意味着您已经拥有了所谓的低优先级线程,并且以超高优先级爆发,不仅损害了应用程序的其余部分,而且损害了系统的其余部分。
(拥有多核系统的最好的事情之一是,这意味着您的计算体验受设置线程优先级的人员的影响较小!)
如果使用调试器停止多线程.NET应用程序并检查线程,您可能会发现除了最高的线程以外,所有其他线程均正常。最高级别的终结器线程是终结器线程,并且它的最高优先级运行是终结器不要花很长时间执行的重要性的原因之一-以最高优先级完成工作是一件坏事,尽管这样做是有道理的在这种情况下,必须尽快结束。
在所有其他情况下,至少有95%的情况是有人设置了线程的优先级,这是一个逻辑错误-大部分时间它什么都不做,其余的事情会变得一团糟。它们可以很好地使用(或者根本不具备这种能力),但是绝对应该将它们放在“高级技术”类别中。 (我喜欢把自己的空闲时间花在尝试多线程技术上,这些技术在大多数时候通常被认为是过度和过早的优化,而且我仍然很少碰到优先事项)。
在您的示例中,优先级的影响很小,因为每个线程都将大部分时间都花在 sleep 上,因此,任何想要CPU时间的线程都可以在需要运行的纳秒时间内获得它。但是,如果您在内核也忙于其他普通线程的机器上运行它,那么整个事情就会变得不必要地变慢。在这种情况下,
thead1
最初不会获得任何CPU时间(因为总是有更高优先级的线程需要CPU),然后在3秒钟后,调度程序将意识到它永远饿死了CPU速度(90亿个CPU周期或90亿个CPU周期)。因此),并使其具有最高优先级的爆发时间足够长,以使其与重要的Windows服务的时间保持一致!幸运的是,它随后进入休眠状态,然后完成一分钟的工作,然后再完成操作,因此它没有害处,但是,如果它做的是真正的事情,则可能会对整个系统的性能产生某些令人讨厌的影响。
关于c# - 线程优先级(如何获得固定顺序),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8683079/