当前位置: 首页 > news >正文

做网站从哪里找货源做的网站怎样适配手机屏幕

做网站从哪里找货源,做的网站怎样适配手机屏幕,医疗做网站,个人网页设计作品html1.线程的概念 单核CPU的计算机中#xff0c;一个时刻只能执行一条指令#xff0c;操作系统以“时间片轮转”的方式实现多个程序“同时”运行。操作系统以进程#xff08;Process#xff09;的方式运行应用程序#xff0c;进程不但包括应用程序的指令流#xff0c;也包括运… 1.线程的概念 单核CPU的计算机中一个时刻只能执行一条指令操作系统以“时间片轮转”的方式实现多个程序“同时”运行。操作系统以进程Process的方式运行应用程序进程不但包括应用程序的指令流也包括运行程序所需的内存、寄存器等资源。因为交替时间很短一般只有几十毫秒人们根本感觉不到如此短暂的停顿所以在表面上看来就像多个工作同时进行似的。因此进程在宏观上是并发进行的在微观上是交替进行的。 后来出现了多线程技术Multi-threading可以通过在一个进程中创建多个线程Threading系统以“时间片轮转”的方式交替执行多个线程使得可以在一个程序中同时执行多项工作。同一个进程中的所有线程共享进程的资源所以它们之间的切换就比进程间的切换快的多因此线程可以看作轻量级进程Lightweight Process。现代的操作系统都是多进程Multi-process的操作系统每个进程中运行一个或多个线程所以大多数时间操作系统中都有多个线程并发运行。操作系统中有专门的调度程序管理线程它根据事先设计好的算法轮流执行每个线程。线程是操作系统进行CPU 调度的基本单位线程的调度是由操作系统自动完成的无须程序员关心。程序员只需编写好线程即可线程的轮转交由操作系统完成。随着多核心CPU的出现使得线程能够真正的实现同步执行多线程技术从此翻开新的篇章。 2.Thread类 一般情况下每开启一个应用程序系统就会创建一个与该程序相关的的进程紧接着进程就会创建一个主线程Main Thread然后从主函数中的代码开始执行。可以在一个应用程序中创建任意多个线程每个线程完成一项任务。C#中线程由System.Threading 命名空间中的Thread 类实现声明语句 Thread workThread new Thread(entryPoint); 其中entryPoint 代表一个入口方法线程的具体代码放在入口方法中系统从入口方法的第一句代码开始执行线程。入口方法的参数和返回值类型由ThreadStart 委托或ParameterizedThreadStart 委托规定。 public delegate void ThresdStart(); public delegate void ParameterizedThreadStart(Object obj); 除了通过委托传递线程的入口方法外还可以通过匿名方法或Lambda表达式创建线程。 Thread drawGraphThreadnew Thread(delegate() { //入口方法中的代码}); Thread drawGraphThreadnew Thread(() { //入口方法中的代码}); 匿名方法可以使用外部变量所以用匿名方法定义的线程可以使用在线程前面定义的变量这弥补了入口方法没有参数和返回值的问题。 3.线程的优先级 计算机中经常会有多个任务同时运行其中总有一些看起来更紧急更需要优先执行。线程的优先级可以通过Thread类Priority属性设置Priority属性是一个ThreadPriority型枚举包含5个优先等级Highest、AboveNormal、Normal BelowNormal、Lowest。应先设置线程优先级再执行线程并且任何一个程序的Main()方法将占用一个主线程。 //改变线程优先级 threadA.Priority ThreadPriority.AboveNormal; threadB.Priority ThreadPriority.BelowNormal; //启动线程 threadA.Start(); threadB.Start(); 4.线程的插入 Thread类的Join()方法能够将两个原本交替执行的线程变为顺序执行。 Using System.Threading; Static void Main(string [] args) { //线程A Thread threadAnew Thread(delegate()   {  for(int i0;i10000000;i)     {   if(i%10000000)         {Console.Write(‘A’); }      } }); //线程B Thread threadBnew Thread(delegate() {  for (int i0;i50000000;i) { if(i%10000000)         {Console.Write(‘B’);}     }    //在这里插入线程A    threadA.Join();    for(int i0;i50000000;i)    {  if(i%100000000)       { Console.Write(‘b’);}    }  }); //启动线程 threadA.Start(); threadB.Start(); } 一开始两个线程交替进行当线程 B 执行到语句“threadA.Join()”时线程A 中剩余的代码插入到线程B 之中从此刻起停止执行线程B专门执行线程A直到执行完线程A 中的所有语句才去执行线程B 中剩余的语句。从线程 B 的角度看在线程B 中调用threadA.Join()相当于在在线程B 中调用了一个方法只有线程threadA 执行完毕之后该方法才会返回Join()方法还可以接受一个表示毫秒数的参数当达到指定时间后即使线程A 还没运行完毕 Join()方法也返回这时线程A 和线程B 再次处于交替运行中。 5.线程的状态 线程的状态由Thread类的ThreadState属性表示   当一个线程被创建后它就处于Unstarted 状态直到调用了Start()方法为止。但处于Running 状态的线程也不是一定正在被CPU 执行可能该线程的时间片刚刚用完CPU 正在处理其他线程过一段时间后才会处理它。 有三种方法使线程由 Running 状态变为WaitSleepJoin 状态。第一种情况是为了保持线程间的同步而使之处于等待状态这一点将在下一节讲到。第二种情况是线程调用了Sleep()方法而处于睡眠状态当达到指定的睡眠时间以后线程将会回到Running 状态。第三种情况是调用了Join()方法比如在线程A 的代码中调用了线程B.Join()方法线程A 将处于WaitSleepJoin 状态直到线程B 结束开始继续执行线程A 时为止。如果当线程处于 Running 状态时调用线程的Suspend()方法线程将由Running 状态变为SuspendedRequested 状态请求挂起状态线程一般会再继续执行几个指令当确保线程在安全的状态下时挂起线程这时线程变为Suspended 状态挂起状态。调用线程的Resume()方法可使线程回到Running 状态。 线程的状态是由操作系统的调度程序决定的所以除了在一些调试方案中一般不使用线程的状态。但线程的Background 状态除外可以通过Thread 类的IsBackground 属性把线程设置为Background 状态。其实后台线程跟前台线程只有一个区别那就是后台线程不妨碍程序的终止。一旦一个应用程序的所有前台线程都终止后CLR 就通过调用任意一个存活中的后台线程的Abort()方法来彻底终止应用程序。另外 Thread 类还有一个IsAlive 属性这是个只读属性用来说明线程已经启动还没有结束。 6.线程的同步  1线程同步的概念 同上运行的线程有的相互间没有任何联系称为无关线程而有些线程之间则是有联系的例如一个线程等待另一个线程的运算结果两个线程共享一个资源等这种线程称为相关线程。例如在网上观看在线视频一个线程下载视频另一个线程播放视频两个线程相互合作才能得到较佳的观看体验。线程的相关性集中体现在对同一资源的访问上把这种多个线程共享的资源称为临界资源它可以是内存中的一个变量也可以是一个文件也可以是一台打印机等。 系统中往往有多个线程交替执行它们被执行的时间是不确定当需要两个线程精确协同工作才能共同完成好一项任务的情况称为线程同步Synchronization。如何保证两个线程同步.NET框架提供了一系列的同步类最常用的包括Interlocked互锁、Monitor管程和Mutex互斥体。 2互锁Interlocked类 通过Interlocked类来控制线程的同步为多个线程共享的变量提供原子操作所谓原子操作是指不会被线程调度机制打断的操作这种操作一旦开始就一直运行到结束。例如 using System.Threading; class Program {  private static char buffer; //缓冲区只能容纳一个字符 //标识量缓冲区中已使用的空间初始值为0 private static long numberOfUsedSpace 0; static void Main(string[] args) { Thread writer new Thread(delegate() { string sentence 无可奈何花落去似曾相识燕归来小园香径独徘徊。; for(int i 0; i 24; i) { //写入数据前检查缓冲区是否已满 while(Interlocked.Read(ref numberOfUsedSpace) 1) {Thread.Sleep(10);} buffer sentence[i]; //向缓冲区写入数据 Interlocked.Increment(ref numberOfUsedSpace); } }); Thread reader new Thread(delegate() {for(int i 0; i 24; i) {//读取数据前检查缓冲区是否为空 while(Interlocked.Read(ref numberOfUsedSpace) 0) {Thread.Sleep(10);} char ch buffer; Console.Write(ch); //读取数据后把缓冲区标记为空由1 变为0 Interlocked.Decrement(ref numberOfUsedSpace); } }); //启动线程 writer .Start(); reader.Start(); } } 3Monitor类 另一种同步方法使用Monitor类它使用独占锁的方式控制线程同步只有获得独占锁的线程才能访问临界资源。当一个线程进入临界区时首先调用Monitor 类的Enter()方法尝试获取临界资源的独占锁若独占锁已被其他线程占用就进入等待状态睡眠在临界资源上直到独占锁没有被其他线程占用该线程就会获取独占锁执行操作临界资源的代码。Monitor 会纪录所有睡眠在临界资源上的线程当线程退出临界区时需要通过调用Monitor 类的Pulse()方法唤醒睡眠在临界资源的线程。Monitor 类的部分方法如下表所示 using System.Threading; class Program {private static char buffer; //用于同步的对象独占锁 private static object lockForBuffer new object(); static void Main(string[] args) {Thread writer new Thread(delegate() { string sentence 无可奈何花落去似曾相识燕归来小园香径独徘徊。; for (int i 0; i 24; i) {  lock(lockForBuffer) { buffer sentence[i]; Monitor.Pulse(lockForBuffer); //唤醒睡眠在此临界资源上的其它线程 Monitor.Wait(lockForBuffer); //让当前线程睡眠在临界资源上 } } }); Thread reader new Thread(delegate() { for (int i 0; i 24; i) { lock (lockForBuffer) { char ch buffer; Console.Write(ch); Monitor.Pulse(lockForBuffer); //唤醒睡眠在临界资源上的线程 Monitor.Wait(lockForBuffer); //让当前线程睡眠在临界资源上} } }); //启动线程 writer .Start(); reader.Start(); } } 实际上旧版的C#中其编码方式如下左图新版的C#对其进行了简化设计了lock(object o){}的方式。   在线程 writer 中因为当缓冲区中的数据被读走以后还要继续向缓冲区中写数据所以当写完数据后调用了Monitor.Wait()方法让线程writer 睡眠在临界资源上直到线程reader 读完数据后把它唤醒。出于同样的理由当线程reader 读完数据后也调用了Monitor.Wait()方法。为了确保退出临界区时临界资源得到释放使用 Monitor 类的代码应该放在try 语句中并在finally 块中调用Monitor.Exit()方法。而简化版的lock 语句执行完毕后会自动执行Monitor.Exit()方法释放临界资源二者功能完全等价。 需要注意的是Monitor 类只能锁定引用类型对象。 当一个线程以独占锁的方式访问资源时其他线程就不能访问该资源只有lock 语句结束后其他线程才能访问。lock 语句的相当于临时禁用了应用程序的多线程功能。一般情况下当有多个线程对同一个资源进行写操作时就应当进行同步操作。但是如果一个线程在某资源上放置了一把锁其他访问该资源的线程就只能暂停使程序的效率大打折扣。所以只有必要的时候才设置独占锁。 4互斥体Mutex类 在操作系统中许多线程常常需要共享资源而这些资源往往要求排他性的使用即一次只能为一个线程服务。比如打印机一次只能打印一个文档一个文件一次只允许一个线程写入数据等。这种排他性地使用共享资源称为线程间的互斥Mutual Exclusion。线程互斥实质上也是同步可以看做一种特殊的线程同步。线程的互斥常用Mutex 类互斥体实现利用它可以对资源进行独占性访问。与Monitor 类相似只有获取Mutex 对象的所属权的线程才能进入临界区未获得Mutex 对象所属权的线程只能在临界区外等待。使用Mutex 类要比使用Monitor 类消耗更多的系统资源但它可以跨越应用程序边界在多个应用程序之间进行同步。Mutex 类的部分方法如下表所示    互斥体有两种类型局部互斥体和系统互斥体。局部互斥体只能在创建它的程序中使用而系统互斥体则能被系统中不同的应用程序共享。创建系统互斥体只需在构造函数中为互斥体对象起一个“系统名称”即可。  操作系统根据互斥体的系统名称辨别互斥体不管互斥体对象创建于哪个应用程序中只要具有相同的系统名称就被认为是同一个系统互斥体。下面分别创建两个程序它们都每隔一秒钟向文件 TimeRecord.txt 中写入一条包含当前系统时间的记录。显然为了保证每条记录的完整性当一个程序向文件中写入记录时另一个程序必须等待。因此需要用Mutex 进行同步。 static void Main(string[] args) { Thread threadAnew Thread(delegate() { Mutex fileMutex new Mutex(false, MutexForTimeRecordFile); string fileName D:\ TimeRecord.txt; for (int i 1; i 10; i) {try{ //请求互斥体的所属权若成功则进入临界区若不成功则等待 fileMutex.WaitOne(); //在临界区中操作临界资源即向文件中写入数据 File.AppendAllText(fileName, threadA: DateTime.Now \r\n); } catch (System.Threading.ThreadInterruptedException) {Console.WriteLine(线程A 被中断。);} finally {fileMutex.ReleaseMutex(); //释放互斥体的所属权} Thread.Sleep(1000); } }); threadA.Start(); } //创建第二个程序MutecB在主函数中输入下面的代码 static void Main(string[] args) { Thread threadB new Thread(delegate() {//创建互斥体 Mutex fileMutex new Mutex(false, MutexForTimeRecordFile); string fileName D:\ TimeRecord.txt; for (int i 1; i 10; i) { try {//请求互斥体的所属权若成功则进入临界区若不成功则等待 fileMutex.WaitOne(); //在临界区中操作临界资源即向文件中写入数据 File.AppendAllText(fileName, threadB: DateTime.Now \r\n); } catch (System.Threading.ThreadInterruptedException) {Console.WriteLine(线程B 被中断。);} finally {fileMutex.ReleaseMutex(); //释放互斥体的所属权} Thread.Sleep(1000); } }); threadB.Start(); System.Diagnostics.Process.Start(MutexA.exe); //启动程序MutexA.exe } 上面两个程序中我们分别创建了一个互斥体对象因为它们的系统名称都是“MutexForTimeRecordFile”所以操作系统认为它们是同一个Mutex 对象从而实现两个应用程序互斥地访问同一个文件。用【生成】菜单中的命令分别生成程序 MutexA.exe 和程序MutexB.exe然后把它们复制到同一个文件夹中。双击程序 MutexB.exe因为程序MutexB.exe 中包含有启动程序MutexA.exe 的代码所以两个程序都被启动。两个程序运行完毕后打开TimeRecord.txt 文件观察结果两个程序实现了交替的向同一文件中写入时间记录。当一个程序向文件中写入文件记录时另一个程序只能处于等待状态从而保证了每条记录的完整性。 5.死锁 多个线程间的同步如果设计不当就会造成死锁Deadlock。死锁是指多个线程共享某些资源时都占用一部分资源而且都在等待对方释放另一部分资源从而导致程序停滞不前的情况。 下面的程序演示了一种典型的死锁情形。一对情侣共吃一份西餐并且共用一副刀叉。只有同时获得刀子和叉子时才可以吃东西吃完以后就放下刀叉供对方使用。如果刀子或叉子正好被对方拿起就只能等待直到对方放下为止。 class Program { private static object knife new object(); //临界资源刀子 private static object fork new object(); //临界资源叉子 static void Main(string[] args) {//线程女孩的行为 Thread girlThread new Thread(delegate() {//女孩和男孩聊天 Console.WriteLine(今天的月亮好美啊~~~); //过了一会儿女孩饿了就去拿刀子和叉子 lock (knife) { GetKnife(); //*待会儿会在这里添加一条语句 lock (fork) { GetFork(); Eat(); //同时拿到刀子和叉子后开始吃东西 Console.WriteLine(女孩放下叉子); Monitor.Pulse(fork); } Console.WriteLine(女孩放下刀子); Monitor.Pulse(knife); } }); girlThread.Name 女孩; //定义线程的名称 //线程男孩的行为 Thread boyThread new Thread(delegate() { //男孩和女孩聊天 Console.WriteLine(\n 你更美); lock (fork) { GetFork(); lock (knife) { GetKnife(); Eat(); //同时拿到刀子和叉子后开始吃东西 Console.WriteLine(男孩放下刀子); Monitor.Pulse(knife); } Console.WriteLine(男孩放下叉子); Monitor.Pulse(fork); } }); boyThread.Name 男孩; //定义线程的名称 //启动线程 girlThread .Start(); boyThread.Start(); } //方法拿起刀子 static void GetKnife() {Console.WriteLine(Thread.CurrentThread.Name 拿起刀子。);} //方法拿起叉子 static void GetFork() {Console.WriteLine(Thread.CurrentThread.Name 拿起叉子。);} //方法吃东西 static void Eat() {Console.WriteLine(Thread.CurrentThread.Name 吃东西。);} } 一般情况下程序可以正常运行结果如下 但在某些特殊情况下就会出现死锁现象。假设女孩刚好拿起了刀子正要拿叉子时操作系统把线程切换到了男孩这时男孩也想吃饭于是拿起了叉子但随即发现刀子已被女孩占有所以男孩线程进入睡眠状态等待女孩释放刀子。过一会儿线程再次切换到女孩当女孩试图拿起叉子时发现叉子已被男孩占有于是女孩线程也进入睡眠状态等待男孩释放叉子。最终男孩等女孩释放刀子女孩等男孩释放叉子双方都在无休止的等待对方进入了死锁状态。 出现死锁的前提条件是两个线程出现交替交替过程中各占有一部分资源而每个线程运行都需要获得整个资源由于例子中的两个线程都很小多数情况下都能在一个时间片内完成所以出现死锁的概率还是很小的。线程运行时间的越长出现交替的情况越多出现死锁的概率越大。 死锁会造成程序停滞不前所以我们在编写多线程程序时一定要注意避免死锁现象的发生。其实上面的问题很好解决只要两个线程以相同的顺序访问临界资源即可。 7.线程池 一般情况下我们都使用Thread类创建线程因为通过Thread对象可以对线程进行灵活的控制。但创建线程和销毁线程代价不菲过多的线程会消耗掉大量的内存和CPU资源假如某段时间内突然爆发了100 个短小的线程创建和销毁这些线程就会消耗很多时间可能比线程本身运行的时间还长。为了改善这种状况.NET提供了一种称之为线程池Thread Pool的技术。线程池提供若干个固定线程轮流为大量的任务服务比如用10 个线程轮流执行100 个任务当一个线程完成任务时并不马上销毁而是接手另一个任务从而减少创建和销毁线程的消耗。线程池由System.Threading 命名空间中的ThreadPool 类实现其部分方法如下表所示 ThreadPool 是一个静态类不必创建实例就可以使用它。一个应用程序最多只有一个线程池它会在首次向线程池中排入工作函数时自动创建。 namespace ThreadPoolTest { class Program { public delegate void WaitCallback(Object dataForFunction); public static void ThreadPoolTest() {//向线程池中添加100个工作线程 for (int i 1; i 100; i) {ThreadPool.QueueUserWorkItem(new WaitCallback(WorkFunction), i);} } //工作函数 public static void WorkFunction(object n) { Console.Write(n \t);} static void Main(string[] args) {ThreadPoolTest(); Console.ReadKey(); //按下任意键结束程序} }} 结果如下图所示 下面研究一下线程池运行过程中线程数目的变化情况从而加深对线程池的理解。为了叙述方便假设下限为10上限为30。 ①当线程池被创建后里面就会创建10 个空线程和下限值相同。 ②当向线程池中排入一个任务后就会有一个空线程接手该任务然后运行起来。随着不断向线程池中排入任务线程池中的空线程逐一运行起来。 ③随任务不断增加某一时刻任务数量会超出下限这时线程数量不够用了但线程池并不会立即创建新线程而是等待500 毫秒左右看看在这段时间是否有其它线程完成任务并接手这个请求避免因创建新线程而造成的消耗。如果这段时间没有线程完成任务就创建一个新线程去执行新任务。 ④在任务数量超过下限后随着新任务的不断排入线程池中线程数量持续增加直至达到上限值为止。 ⑤当线程数量达到上限时继续增加任务线程数量将不再增加。多余的任务就线程池外排队等待。线程池某个线程完成任务后就从等待队列中选择一个任务继续执行。 ⑥随着任务逐步完成线程池外部等候的任务被逐步调入线程池任务的数量逐步减少但线程的总数保持恒定始终为30和上限值相同。 ⑦随着任务的逐渐减少某一时刻任务数量会小于上限值这时线程池内多余的线程会在空闲2 分钟后被释放并回收相关资源。线程数目逐步减少直到达到下限值。 ⑧当任务数量减小到下限值之下时线程池中的线程数目保持不变始终和下限值相同其中一部分在执行任务另一部分处于空运行状态。 ⑨当所有任务都完成后线程池恢复初始状态运行10 个空线程。 由上面的论述可以看出线程池提高效率的关键是一个线程完成任务后可以继续为其他任务服务这样就可以使用有限的几个固定线程轮流为大量的任务服务从而减少了因频繁创建和销毁线程所造成的消耗。ThreadPool 中的线程不用手动开始也不能手动取消你要做的只是把工作函数排入线程池剩下的工作将由系统自动完成。如果想对线程进行更多的控制那么就不适合使用线程池。在以下情况中不宜使用ThreadPool类而应该使用单独的Thread 类 ①线程执行需要很长时间如果有些线程长期占用线程池那么对在外面排队的任务说就是灾难 ②需要为线程指定详细的优先级 ③在执行过程中需要对线程进行操作比如睡眠挂起等。 所以 ThreadPool 适合于并发运行若干个运行时间不长且互不干扰的函数。    转载于:https://www.cnblogs.com/Sweepingmonk/p/10868056.html
http://www.zqtcl.cn/news/74467/

相关文章:

  • 深圳模板开发建站自助服务平台
  • 推广网站的网址和网鱼相匹配如何在淘宝客上做自己的网站
  • 分析公司网站的开发策略苏州建设交通职业技术学院官网
  • 专业的家居行业网站模板大连金州旅游景点有哪些
  • 手机网站设计公司只选亿企邦网页制作简明教程
  • 做做网站下载免费深圳今天新增确诊名单
  • 电子商务网站建设与管理实验手机网站排行榜
  • 摄影网站难做吗关键词快速排名平台
  • 南京 网站建设有限公司餐饮行业做网站的数据
  • 中山建设网站公司扬州网络推广外包
  • 企业网站开发周期企业名称预先核准网上申请
  • 网站架构的优化小红书推广运营
  • 把网站做二维码咸宁商城网站建设
  • 网站建设及推广服务公司wordpress 主题显示
  • 网站信息建设总结苏州网页设计费用
  • 做网站怎么返回首页手机网站背景图尺寸
  • 怎么创立网站企业网站设计与制作
  • 锦州网站建设锦州永康电子商务网站建设
  • 深圳工程建设信息网站网站做m版
  • 电子公司网站源码沈阳定制网红小熊花的地方
  • 论坛的网站开发项目备案网站域名和主机关系
  • 如何提高网站pr值湖州服装网站建设
  • 四川移动端网站建设人才网站app建设建议
  • 建设网站后申请什么类型专利wordpress评论框加
  • 网站开发与维护考察试题ios wordpress连接站点
  • 网站关键词排名忽然wordpress文件读取漏洞
  • app展示网站模板南岗红旗大街网站建设
  • 合肥高新区建设发展局网站网站开发公司东莞
  • 腾讯云ADM怎么做网站代写软文
  • 怎么使网站降权知名网站定制公司电话