线程的优先级和线程让步yield
- 格式:doc
- 大小:21.50 KB
- 文档页数:3
线程池调度策略
线程池调度策略是指在多线程程序中,如何合理地分配和调度各个线程的任务执行。
主要有以下几种调度策略:
1.优先级调度:根据线程的优先级来决定执行顺序,优先级高的线程优先执行。
优先级可以根据线程的属性、任务紧急程度等因素来设定。
2.先来先服务(FCFS):线程提交任务后,按照提交的顺序依次执行。
这种策略简单易实现,但可能导致优先级低的线程长时间得不到执行。
3.最短作业优先(SJF):根据任务估计执行时间的长短来决定执行顺序,执行时间短的线程优先执行。
这种策略能有效减少平均等待时间,但可能导致执行时间长的任务长时间得不到执行。
4.优先级反转:结合优先级调度和先来先服务策略,优先级高的线程在等待时间较长时,可以降低优先级,让优先级低的线程先执行。
这样可以避免低优先级任务长时间得不到执行的问题。
5.时间片轮转:为每个线程分配一个固定的时间片,线程按照顺序执行。
当一个线程的时间片用完后,切换到下一个线程。
这种策略实现了线程的公平执行,但可能导致响应速度较慢。
6.多级反馈队列:将线程分为多个队列,根据线程的优先级和执行情况动态调整队列。
优先级高的线程放在前列,优先执行。
这种策略综合了优先级调度和时间片轮转的优点,实现了较好的
性能。
在实际应用中,可以根据具体需求和场景选择合适的线程池调度策略。
编程思想之多线程与多进程(2)——线程优先级与线程安全线程优先级现在主流操作系统(如Windows、Linux、Mac OS X)的任务调度除了具有前面提到的时间片轮转的特点外,还有优先级调度(Priority Schedule)的特点。
优先级调度决定了线程按照什么顺序轮流执行,在具有优先级调度的系统中,线程拥有各自的线程优先级(Thread Priority)。
具有高优先级的线程会更早地执行,而低优先级的线程通常要等没有更高优先级的可执行线程时才会被执行。
线程的优先级可以由用户手动设置,此外系统也会根据不同情形调整优先级。
通常情况下,频繁地进入等待状态(进入等待状态会放弃之前仍可占用的时间份额)的线程(如IO线程),比频繁进行大量计算以至于每次都把所有时间片全部用尽的线程更受操作系统的欢迎。
因为频繁进入等待的线程只会占用很少的时间,这样操作系统可以处理更多的任务。
我们把频繁等待的线程称之为IO密集型线程(IO Bound Thread),而把很少等待的线程称之为CPU密集型线程(CPU Bound Thread)。
IO密集型线程总是比CPU密集型线程更容易得到优先级的提升。
线程饿死:在优先级调度下,容易出现一种线程饿死的现象。
一个线程饿死是说它的优先级较低,在它执行之前总是有比它优先级更高的线程等待执行,因此这个低优先级的线程始终得不到执行。
当CPU密集型的线程优先级较高时,其它低优先级的线程就很可能出现饿死的情况;当IO密集型线程优先级较高时,其它线程相对不容易造成饿死的善,因为IO线程有大量的等待时间。
为了避免线程饿死,调度系统通常会逐步提升那些等待了很久而得不到执行的线程的优先级。
这样,一个线程只要它等待了足够长的时间,其优先级总会被提升到可以让它执行的程度,也就是说这种情况下线程始终会得到执行,只是时间的问题。
在优先级调度环境下,线程优先级的改变有三种方式:1. 用户指定优先级;2. 根据进入等待状态的频繁程度提升或降低优先级(由操作系统完成);3. 长时间得不到执行而被提升优先级。
LabVIEW 程序中的线程3 - 线程的优先级三、线程的优先级在VI 的属性设置面板VI Properties -> Execution 中还有一个下拉选项控件是用来设置线程优先级的(Priority)。
这一选项可以改变这个VI 运行线程的优先级。
优先级设置中共有六项,其中前五项是分别从低到高的五个优先级。
优先级越高,越容易抢占到CPU 资源。
比如你把某个负责运算的VI 的优先级设为最高级(time critical priority),程序在运行时,CPU 会更频繁地给这个VI 所在线程分配时间片段,其代价是分配给其它线程的运算时间减少了。
如果这个程序另有一个线程负责界面刷新,那么用户会发现在把执行线程的优先级提高后,界面刷新会变得迟钝,甚至根本就没有响应。
优先级设置的最后一项是subroutine,它与前五项别有很大的不同。
严格的说subroutine 不能作为一个优先级,设置subroutine 会改变VI 的一些属性:设置为subroutine 的VI 的前面板的信息会被移除。
所以这样的VI 不能用作界面,也不能单独执行。
设置为subroutine 的VI 的调试信息也会被移除。
这样的VI 无法被调试。
当程序执行到被设置为subroutine 的VI 的时候,程序会暂时变为单线程执行方式。
即程序在subroutine VI 执行完之前,不会被别的线程打断。
以上的三点保证了subroutine VI 在执行时可以得到最多的CPU 资源,某些作为关键运算的VI,又不是特别耗时的,就可以被设置为subroutine 以提高运行速度。
比如有这样一个VI,他的输入是一个数值数组,输出是这组数据的平均值。
这个运算在程序中需要被尽快完成,以免拖延数据的显示,这个VI 就是一个蛮适合的subroutine VI。
在设置VI 优先级的时候有几点需要注意的。
提高一个VI 的优先级一般不能显著缩短程序的运行时间。
【转】pthread设置线程的调度策略和优先级线程的调度有三种策略:SCHED_OTHER、SCHED_RR和SCHED_FIFO。
Policy⽤于指明使⽤哪种策略。
下⾯我们简单的说明⼀下这三种调度策略。
SCHED_OTHER(是Linux默认的分时调度策略)它是默认的线程分时调度策略,所有的线程的优先级别都是0,线程的调度是通过分时来完成的。
简单地说,如果系统使⽤这种调度策略,程序将⽆法设置线程的优先级。
请注意,这种调度策略也是抢占式的,当⾼优先级的线程准备运⾏的时候,当前线程将被抢占并进⼊等待队列。
这种调度策略仅仅决定线程在可运⾏线程队列中的具有相同优先级的线程的运⾏次序。
SCHED_FIFO它是⼀种实时的先进先出调⽤策略,且只能在超级⽤户下运⾏。
这种调⽤策略仅仅被使⽤于优先级⼤于0的线程。
它意味着,使⽤SCHED_FIFO的可运⾏线程将⼀直抢占使⽤SCHED_OTHER的运⾏线程J。
此外SCHED_FIFO是⼀个⾮分时的简单调度策略,当⼀个线程变成可运⾏状态,它将被追加到对应优先级队列的尾部((POSIX 1003.1)。
当所有⾼优先级的线程终⽌或者阻塞时,它将被运⾏。
对于相同优先级别的线程,按照简单的先进先运⾏的规则运⾏。
我们考虑⼀种很坏的情况,如果有若⼲相同优先级的线程等待执⾏,然⽽最早执⾏的线程⽆终⽌或者阻塞动作,那么其他线程是⽆法执⾏的,除⾮当前线程调⽤如pthread_yield之类的函数,所以在使⽤SCHED_FIFO的时候要⼩⼼处理相同级别线程的动作。
SCHED_RR鉴于SCHED_FIFO调度策略的⼀些缺点,SCHED_RR对SCHED_FIFO做出了⼀些增强功能。
从实质上看,它还是SCHED_FIFO调⽤策略。
它使⽤最⼤运⾏时间来限制当前进程的运⾏,当运⾏时间⼤于等于最⼤运⾏时间的时候,当前线程将被切换并放置于相同优先级队列的最后。
这样做的好处是其他具有相同级别的线程能在“⾃私“线程下执⾏。
linux 线程优先级设置方法Linux操作系统中,线程是轻量级的进程,合理设置线程的优先级可以优化系统资源的分配,提高程序的执行效率。
本文将详细介绍Linux线程优先级的设置方法。
一、线程优先级概述在Linux操作系统中,线程优先级通常分为两种:静态优先级和动态优先级。
1.静态优先级:在创建线程时分配的优先级,通常在程序运行过程中不会改变。
2.动态优先级:系统根据线程的运行情况动态调整的优先级,通常与线程的CPU使用时间、等待时间等因素有关。
二、设置线程优先级的方法1.使用sched_setparam()函数设置静态优先级函数原型:```cint sched_setparam(pid_t pid, const struct sched_param *param);```示例代码:```c#include <stdio.h>#include <unistd.h>#include <sched.h>#include <pthread.h>void *thread_function(void *arg) {// 线程函数代码}int main() {pthread_t tid;struct sched_param param;int policy;// 创建线程pthread_create(&tid, NULL, thread_function, NULL);// 获取当前线程的调度策略和优先级pthread_getschedparam(pthread_self(), &policy, ¶m);// 设置优先级(数值越大,优先级越高)param.sched_priority = 30;// 设置线程优先级if (pthread_setschedparam(tid, policy, ¶m) != 0) { perror("pthread_setschedparam");return 1;}// 等待线程结束pthread_join(tid, NULL);return 0;}```2.使用nice()函数设置动态优先级函数原型:```cint nice(int inc);```示例代码:```c#include <stdio.h>#include <unistd.h>#include <sys/resource.h>int main() {// 获取当前进程的nice值int old_nice = nice(0);// 设置新的nice值(数值越小,优先级越高)if (nice(-10) == -1) {perror("nice");return 1;}// 输出新的优先级printf("New priority: %d", old_nice - 10);return 0;}```三、总结本文介绍了Linux线程优先级的设置方法,包括使用sched_setparam()函数设置静态优先级和使用nice()函数设置动态优先级。
2、线程的优先级和线程让步yield()线程的让步是通过Thread.yield()来实现的。
yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程。
要理解yield(),必须了解线程的优先级的概念。
线程总是存在优先级,优先级范围在1~10之间。
JVM线程调度程序是基于优先级的抢先调度机制。
在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。
但这仅仅是大多数情况。
注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。
因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。
当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。
这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。
二是时间分片,为池内的每个线程提供均等的运行机会。
设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。
可以通过setPriority(int newPriority)更改线程的优先级。
例如:Thread t = new MyThread();t.setPriority(8);t.start();线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。
然而,1~10之间的值是没有保证的。
一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。
线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围:static int MAX_PRIORITY线程可以具有的最高优先级。
static int MIN_PRIORITY线程可以具有的最低优先级。
static int NORM_PRIORITY分配给线程的默认优先级。
3、Thread.yield()方法Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。
yield的用法详解一、什么是yield?yield是Python中的一个关键字,用于生成器函数(generator function)中。
生成器函数是一种特殊的函数,它可以在调用时暂停执行,并且在下次调用时从上次暂停的位置继续执行。
二、yield的基本语法在生成器函数中,我们可以使用yield语句将一个值返回给调用者。
以下是yield语句的基本语法:```pythonyield expression```其中,expression表示要返回的值。
三、yield语句工作原理当生成器函数被调用时,它并不会立即执行内部代码,而是返回一个迭代器(iterator)。
每次调用迭代器的__next__()方法或使用for循环进行迭代时,生成器函数才会开始执行内部代码,并在遇到yield语句时暂停执行,并将 yield 后面的表达式作为返回值。
四、生成器函数中多个yield语句的执行顺序在生成器函数内部可以有多个 yielf 语句。
当生成器被调用时,会按照顺序依次执行每个 yield 语句,并在每次遇到 yield 时暂停并返回一个值。
下次调用迭代器的__next__()方法或使用 for 循环进行迭代时,则会从上一次暂停处继续执行。
五、通过for循环迭代生成器生成器函数通常与 for 循环一起使用,方便迭代生成器的返回值。
当使用 for 循环迭代生成器时,会自动调用迭代器的__next__()方法,并将返回值赋值给循环变量。
六、利用yield实现惰性求值惰性求值是一种节省资源的编程技巧,它允许在需要时逐步计算结果。
生成器函数中的 yield 语句可以实现这一特性。
当生成器函数内部存在复杂且耗时的计算过程时,可以使用 yield 在每次迭代时进行部分计算并返回中间结果,从而避免处理大量数据导致的内存占用和时间开销。
七、应用场景举例-斐波那契数列斐波那契数列是一个经典的应用场景,可以通过生成器函数和 yield 语句非常简洁地实现。
改变线程优先级的方法在 Java 中,可以通过设置线程的优先级来改变线程的执行顺序。
线程的优先级范围从1 到 10,其中 1 表示最低优先级,10 表示最高优先级。
以下是几种常见的改变线程优先级的方法:1. 使用`setPriority()`方法:可以通过调用线程对象的`setPriority()`方法来设置线程的优先级。
该方法接受一个整数参数,用于指定线程的优先级。
例如:```javaThread thread = new Thread();thread.setPriority(5);```2. 使用`Priority`类:Java 提供了`Priority`类,它包含了常量表示不同的优先级。
可以使用这些常量来设置线程的优先级。
例如:```javaThread thread = new Thread();thread.setPriority(Priority.NORMAL);```3. 使用`thread`类的构造函数:在创建线程时,可以通过传递优先级参数来设置线程的优先级。
例如:```javaThread thread = new Thread(Priority.HIGH);```需要注意的是,线程的优先级并不能保证线程的执行顺序,只是在系统调度线程时提供了一种参考。
系统可能会根据其他因素(如进程的状态、资源需求等)来决定线程的执行顺序。
而且,高优先级的线程并不一定总是先执行,低优先级的线程也可能会在高优先级的线程之前执行。
在实际应用中,应该谨慎使用线程优先级,避免滥用高优先级导致其他线程饥饿。
通常情况下,使用默认的优先级即可满足大多数需求。
如果确实需要调整线程优先级,应该根据具体情况进行评估,并确保代码在不同的平台和环境下具有可移植性。
java yield方法在Java中,yield方法是用来改变线程优先级的一种方法,它可以让处于相同优先级的线程之间形成竞争,也就是说,当一个线程调用yield方法时,它将暂停执行,让出处理器,让具有相同优先级的其他线程有机会获得执行权。
Yield方法是ng.Thread类的一个静态方法,它没有任何参数。
当一个线程调用它时,当前线程暂停执行,让出处理器,让具有相同优先级的其他线程有机会获得执行权。
Yield方法有一个重要的特性,它只让跟当前线程具有相同优先级的线程可以获得处理器执行权,如果没有这样的线程,当前线程继续执行。
在Java语言中,线程的优先级由操作系统在创建线程时从Thread类的类变量中取出,线程创建时的默认优先级设置为NORM_PRIORITY。
如果线程的优先级被改变了,可以使用yield方法来改变线程的优先级,使其有机会获得处理器资源。
Yield方法应该在何时被调用?Yield方法应该在处理器同时执行多个线程时被调用,以平衡处理器负载,保证各个线程都能够获得执行机会。
但是,在实际应用中,一般不会使用yield方法,因为它会导致系统的性能下降。
使用yield方法的另一个重要原因是避免竞争。
在Java中,线程使用共享内存访问共享资源,当多个线程争夺相同的资源时,就会发生线程竞争,导致系统性能下降。
如果一个线程调用了yield 方法,那么它就可以把资源让给另外一个线程,从而避免线程竞争,提高系统性能。
另外,yield方法还可以用来减少执行时间,特别是在多线程编程中,如果某个线程已经完成了某项任务,可以使用yield方法来放弃当前的处理器,让出资源给其他任务。
总的来说,Yield方法可以在改变线程优先级时使用,它可以使处于相同优先级的线程间形成竞争,以此改变线程优先级,避免竞争,减少执行时间。
Yield方法是一个很有用的方法,可以提高系统的性能。
进程系统分配调度的基本单位,线程进⾏运算调度的最⼩单位进程和线程⽣命周期进程的状态线程的同步和互斥进程是计算机中程序关于某数据集合上的⼀次运⾏活动,是系统进⾏资源分配和调度的基本单位进程的状态:⼀个进程的⽣命周期可以划为⼀组状态,这些状态刻画了整个进程,进程状态即体现⼀个进程的⽣命状态。
进程有⼏种状态:就绪状态、运⾏状态、阻塞状态当然理论上上述三种状态之间转换分为六种情况;运⾏——>就绪:1,主要是进程占⽤CPU的时间过长,⽽系统分配给该进程占⽤CPU的时间是有限的;2,在采⽤抢先式优先级调度算法的系统中,当有更⾼优先级的进程要运⾏时,该进程就被迫让出CPU,该进程便由执⾏状态转变为就绪状态。
就绪——>运⾏:运⾏的进程的时间⽚⽤完,调度就转到就绪队列中选择合适的进程分配CPU运⾏——>阻塞:正在执⾏的进程因发⽣某等待事件⽽⽆法执⾏,则进程由执⾏状态变为阻塞状态,如发⽣了I/O请求阻塞——>就绪:进程所等待的事件已经发⽣,就进⼊就绪队列以下两种状态是不可能发⽣的:阻塞——>运⾏:即使给阻塞进程分配CPU,也⽆法执⾏,操作系统在进⾏调度时不会从阻塞队列进⾏挑选,⽽是从就绪队列中选取就绪——>阻塞:就绪态根本就没有执⾏,谈不上进⼊阻塞态。
在⼀些系统中,⼜增加了⼀些新状态,如挂起状态,可运⾏状态,深度睡眠状态,浅度睡眠状态,暂停状态,僵死状态。
线程:线程⽣命周期:线程的⽣命周期:新⽣,线程被实例化,还未被执⾏;就绪,没有抢到cpu时间⽚;运⾏,抢到了时间⽚,cpu开始处理这个线程中的任务;阻塞,线程在执⾏过程中遇到特殊情况,使得其他线程能获得执⾏的机会,被阻塞的线程会等待合适的时机,进⼊就绪状态;死亡,线程终⽌;线程的合并;.join( ) 当前线程将会释放CPU资源,cpu将时间⽚分给要join的线程线程的让步; .yield( ) 当前线程列表⾥优先级⾼于当前线程的可以抢这个CPU资源互斥:指某⼀时刻允许⼀个进程运⾏其中的程序⽚,具有排他性和唯⼀性同步:指在互斥基础上实现进程之间的有序访问,假设现有线程A和线程B,线程A需要往缓冲区写数据,线程B需要从缓冲区读数据,但她们存在⼀种制约关系,即线程A写的时候,B不能读数据,线程B在读数据的时候,A不能写,也即当A写完数据(或B取⾛数据),B才能来拿数据临界资源:能够被多个线程共享的数据/资源。
进程优先级与线程优先级学习各种高级外挂制作技术,马上去百度搜索"魔鬼作坊",点击第一个站进入,快速成为做挂达人。
SetThreadPriority与SetPriorityClass区别知识点:线程优先级获取当前线程句柄线程优先级设置线程优先级变动线程优先级获取线程优先级(Thread priority)简单的说就是(线程)的优先级越高,那么就可以分占相对多的CPU时间片。
每个进程都有相应的优先级,优先级决定它何时运行和占用CPU时间。
最终的优先级共分32级,是从0到31的数值,称为基本优先级别。
进程优先级priority class标志优先级值idle(低)IDLE_PRIORITY_CLASS4Below低于标准BELOW_NORMAL_PRIORITY_CLASS此值在2000以下系统不支持normal(标准)NORMAL_PRIORITY_CLASS9(前台)或7(后台) Above高于标准ABOVE_NORMAL_PRIORITY_CLASS此值在2000以下系统不支持high(高)HIGH_PRIORITY_CLASS13realtime(实时)REALTIME_PRIORITY_CLASS24一个线程创建的时候,会继承进程的优先级等级。
另外线程优先级可以用SetThreadPriority 来进行微调:线程优先级等级标志优先级值1idle(最低)THREAD_PRIORITY_IDLE如果进程优先级为realtime则调整为16,其它情况为12LOWEST低THREAD_PRIORITY_LOWEST-2(在原有基础上-2)3BELOW低于标准THREAD_PRIORITY_BELOW_NORMAL -1(在原有基础上-1)4NORMAL(标准)THREAD_PRIORITY_NORMAL不变(取进程优先级值)5ABOVE高于标准THREAD_PRIORITY_ABOVE_NORMAL+1(在原有基础上+1)6HIGHEST(高)THREAD_PRIORITY_HIGHEST+2(在原有基础上+2)7CRITICAL(最高)THREAD_PRIORITY_TIME_CRITICAL如果进程优先级为realtime则调整为31,其它情况为15二、获取当前线程句柄HANDLE GetCurrentThread(VOID)//返回当前进句柄DWORD GetCurrentThreadId(VOID)//返回当前进程ID值1、其它线程函数BOOL SetThreadPriority设置一个线程的优先级别int GetThreadPriority返回一个线程的优先级别SetThreadPriorityBoost设置线程是否禁用动态调整优先级功能。
详解Java中的线程让步yield()与线程休眠sleep()⽅法线程让步: yield()yield()的作⽤是让步。
它能让当前线程由“运⾏状态”进⼊到“就绪状态”,从⽽让其它具有相同优先级的等待线程获取执⾏权;但是,并不能保证在当前线程调⽤yield()之后,其它具有相同优先级的线程就⼀定能获得执⾏权;也有可能是当前线程⼜进⼊到“运⾏状态”继续运⾏!⽰例:class ThreadA extends Thread{public ThreadA(String name){super(name);}public synchronized void run(){for(int i=0; i <10; i++){System.out.printf("%s [%d]:%d\n", this.getName(), this.getPriority(), i);// i整除4时,调⽤yieldif (i%4 == 0)Thread.yield();}}}public class YieldTest{public static void main(String[] args){ThreadA t1 = new ThreadA("t1");ThreadA t2 = new ThreadA("t2");t1.start();t2.start();}}(某⼀次的)运⾏结果:t1 [5]:0t2 [5]:0t1 [5]:1t1 [5]:2t1 [5]:3t1 [5]:4t1 [5]:5t1 [5]:6t1 [5]:7t1 [5]:8t1 [5]:9t2 [5]:1t2 [5]:2t2 [5]:3t2 [5]:4t2 [5]:5t2 [5]:6t2 [5]:7t2 [5]:8t2 [5]:9结果说明:“线程t1”在能被4整数的时候,并没有切换到“线程t2”。
细说C#多线程那些事-线程同步和多线程优先级上个⽂章分享了⼀些多线程的⼀些基础的知识,今天我们继续学习。
⼀、Task类上次我们说了线程池,线程池的QueueUserWorkItem()⽅法发起⼀次异步的线程执⾏很简单但是该⽅法最⼤的问题是没有⼀个内建的机制让你知道操作什么时候完成,有没有⼀个内建的机制在操作完成后获得⼀个返回值。
为此,可以使⽤System.Threading.Tasks中的Task类。
Task类在命名空间System.Threading.Tasks下,通过Task的Factory返回TaskFactory类,以TaskFactory.StartNew(Action)⽅法可以创建⼀个新的异步线程,所创建的线程默认为后台线程,不会影响前台UI窗⼝的运⾏。
如果要取消线程,可以利⽤CancellationTakenSource对象。
如果要在取消任务后执⾏⼀个回调⽅法,则可以使⽤Task的()⽅法。
简单代码实现:using System;using System.Threading.Tasks;namespace Threading{class Program{public static Int32 ThreadSum(Int32 n){Int32 sum = 0;for (; n > 0; --n)sum += n;return sum;}static void Main(string[] args){var t = new Task<Int32>(n => ThreadSum((Int32)n), 100);t.Start();var cwt = t.ContinueWith(task => Console.WriteLine("The result is {0}", t.Result));Console.ReadKey();}}}Task类⽰例代码using System;using System.Threading.Tasks;public class Example{public static void Main(){Task t = Task.Factory.StartNew( () => {int ctr = 0;for (ctr = 0; ctr <= 1000000; ctr++){}Console.WriteLine("Finished {0} loop iterations",ctr);} );t.Wait();}}更多内容参考:⼆、异步执⾏委托的异步执⾏代码:BeginInvoke() 和 EndInvoke()using System;namespace Threading{public delegate string MyDelegate(object data);class Program{public static string Thread1(object data){return data.ToString();}public static void ThreadCallback(IAsyncResult data){Console.WriteLine("ThreadCallback = > " + data.AsyncState);}static void Main(string[] args){var mydelegate = new MyDelegate(Thread1);IAsyncResult result = mydelegate.BeginInvoke("Thread1 Para", ThreadCallback, "Callback Para");//异步执⾏完成var resultstr = mydelegate.EndInvoke(result);Console.WriteLine(resultstr);Console.ReadKey();}}}委托异步执⾏⽰例代码三、线程同步线程同步:指多个线程协同、协助、互相配合。
C#教程:线程的优先权C#教程:线程的优先权来源:原创作者:小人物录入时间:2009-09-28内容导读:每个线程都具有分配给它的线程优先级。
为在公共语言运行库中创建的线程最初分配的优先级为ThreadPriority.Normal。
在运行库外创建的线程会保留它们在进入托管环境之前所具有的优先级线程的优先权每个线程都具有分配给它的线程优先级。
为在公共语言运行库中创建的线程最初分配的优先级为ThreadPriority.Normal。
在运行库外创建的线程会保留它们在进入托管环境之前所具有的优先级。
用户可以使用Thread.Priority属性获取或设置任何线程的优先级。
线程是根据其优先级而调度执行的。
即使线程正在运行库中执行,所有线程都是由操作系统分配处理器时间片的。
用于确定线程执行顺序的调度算法的详细情况随每个操作系统的不同而不同。
在某些操作系统下,具有最高优先级(相对于可执行线程而言)的线程经过调度后总是首先运行。
如果具有相同优先级的多个线程都可用,则计划程序将遍历处于该优先级的线程,并为每个线程提供一个固定的时间片来执行。
如果在给定的优先级上不再有可运行的线程,则计划程序将移到下一个较低的优先级并在该优先级上调度线程以执行。
如果具有较高优先级的线程可以运行,则具有较低优先级的线程将被抢先,并允许具有较高优先级的线程再次执行。
除此之外,当应用程序的用户界面在前台和后台之间移动时,操作系统还可以动态调整线程优先级。
其他操作系统可以选择使用不同的调度算法。
可以为线程分配以下任何一个优先级值,如下所示。
HighestAboveNormalNormalBelowNormalLowest示例线程的优先级下面的示例展示了如何使用优先级。
using System;using System.Threading;class Test{static void Main(){PriorityT est priorityTest = new PriorityTest();Thread threadOne = new Thread(new ThreadStart(priorityTest.ThreadMethod)); = "线程1";Thread threadTwo = new Thread(new ThreadStart(priorityTest.ThreadMethod)); = "线程2";threadTwo.Priority = ThreadPriority.BelowNormal;threadOne.Start();threadTwo.Start();// 线程休眠20sThread.Sleep(20000);priorityT est.LoopSwitch = False;}}class PriorityT est{bool loopSwitch;public PriorityTest(){loopSwitch = True;}public bool LoopSwitch{set{ loopSwitch = value; }}public void ThreadMethod(){long threadCount = 0;while(loopSwitch){threadCount++;}Console.WriteLine("{0} with {1,11} priority " +"has a count = {2,13}", , Thread.CurrentThread.Priority.ToString(), threadCount.T oString("N0"));}}完整程序代码如下:★★★★★Program.cs主程序文件完整程序代码★★★★★using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace _8_03{class Test{static void Main(string[] args){PriorityT est priorityTest = new PriorityTest();Thread threadOne = new Thread(new ThreadStart(priorityTest.ThreadMethod)); = "线程1";Thread threadTwo = new Thread(new ThreadStart(priorityTest.ThreadMethod)); = "线程2";threadTwo.Priority = ThreadPriority.BelowNormal;threadOne.Start();threadTwo.Start();// 线程休眠20秒Thread.Sleep(20000);priorityT est.LoopSwitch = false;}}class PriorityT est{bool loopSwitch;public PriorityTest(){loopSwitch = true;}public bool LoopSwitch{set { loopSwitch = value; }}public void ThreadMethod(){long threadCount = 0;while (loopSwitch)Tags:网络编程C#教程责任编辑:adminC#教程:线程的优先权(2)来源:原创作者:小人物录入时间:2009-09-28内容导读:{ threadCount++; } Console.WriteLine({0} with {1,11} priority + has a count = {2,13}, ,Thread.CurrentThread.Priority.ToString(),threadCount.T oString(N0)); } } }{threadCount++;}Console.WriteLine("{0} with {1,11} priority " +"has a count = {2,13}", ,Thread.CurrentThread.Priority.ToString(),threadCount.T oString("N0"));}}}。
线程顺序执行的8种方法线程顺序执行的8种方法在多线程编程中,线程的执行顺序往往是无法预测的。
然而,有时我们需要确保线程按照特定的顺序执行,以避免产生竞争条件或其他不可预料的错误。
本文将介绍8种常见的方法,可以实现线程的顺序执行。
1. 使用join方法join方法可以用于阻塞当前线程,直到调用该方法的线程执行完毕。
我们可以依次创建多个线程,并在主线程中逐个调用每个线程的join方法,从而实现线程的顺序执行。
import threadingdef task():print("Thread execution")threads = []for i in range(5):t = (target=task)(t)()()2. 使用锁锁是一种机制,可以用于保证在同一时间只有一个线程可以访问某个共享资源。
利用锁,我们可以控制线程的执行顺序。
import threadinglock = ()def task():()try:print("Thread execution")finally:()threads = []for i in range(5):t = (target=task)(t)()3. 使用信号量信号量是一种计数器,用于控制对共享资源的访问。
每当一个线程访问共享资源时,信号量的计数器减1;当计数器为0时,其他线程将被阻塞。
通过设置不同的初始值,我们可以实现线程的有序执行。
import threadingsemaphore = ()def task():()try:print("Thread execution")finally:()threads = []for i in range(5):t = (target=task)(t)()4. 使用条件变量条件变量是一种机制,可以让线程等待某个条件变为真时再继续执行。
通过设置不同的条件和对应的线程等待顺序,我们可以实现线程的顺序执行。
线程的优先级设置与调度方法1、线程的优先级线程的优先级是指线程在被系统调度执行时的优先级级别。
在多线程程序中,往往是多个线程同时在就绪队列中等待执行。
优先级越高,越先执行;优先级越低,越晚执行;优先级相同时,则遵循队列的“先进先出”原则。
Thread类有三个与线程优先级有关的静态变量,其意义如下:➢MIN_PRIORITY:线程能够具有的最小优先级(1)。
➢MAX_PRIORITY:线程能够具有的最大优先级(10)。
➢NORM_PRIORITY:线程的普通优先级,默认值是5。
提示:当创建线程时,优先级默认为由NORM_PRIORITY标识的整数(5)。
可以通过setPriority()方法设置线程的优先级,也可以通过getPriority()方法获得线程的优先级。
【例】class MyThread2 extends Thread {public void run() {for (inti = 0; i< 5; i++) {System.out.println(i + " " + getName() + "优先级是:" + getPriority()); } }}public class ThreadExample3 {public static void main(String args[]) {MyThread2 t1 = new MyThread2(); // 创建线程类MyThread2的实例t1MyThread2 t2 = new MyThread2(); // 创建线程类MyThread2的实例t2t1.setPriority(1); // 设置线程t1的优先级为1t2.setPriority(10); // 设置线程t2的优先级为10t1.start(); t2.start(); // 启动线程t1,t2}}2、线程休眠3、线程让步对于正在运行的线程,可以调用yield()方法使其重新在就绪队列中排队,并将CPU资源让给排在队列后面的线程,此线程转为就绪状态。
2、线程的优先级和线程让步yield()
线程的让步是通过Thread.yield()来实现的。
yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程。
要理解yield(),必须了解线程的优先级的概念。
线程总是存在优先级,优先级范围在1~10之间。
JVM线程调度程序是基于优先级的抢先调度机制。
在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。
但这仅仅是大多数情况。
注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。
因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。
当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。
这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。
二是时间分片,为池内的每个线程提供均等的运行机会。
设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。
可以通过setPriority(int newPriority)更改线程的优先级。
例如:
Thread t = new MyThread();
t.setPriority(8);
t.start();
线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。
然而,1~10之间的值是没有保证的。
一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。
线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围:
static int MAX_PRIORITY
线程可以具有的最高优先级。
static int MIN_PRIORITY
线程可以具有的最低优先级。
static int NORM_PRIORITY
分配给线程的默认优先级。
3、Thread.yield()方法
Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。
yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。
因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。
但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
结论:yield()从未导致线程转到等待/睡眠/阻塞状态。
在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
4、join()方法
Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。
在A执行完毕之前,B不能工作。
例如:
Thread t = new MyThread();
t.start();
t.join();
另外,join()方法还有带超时限制的重载版本。
例如t.join(5000);则让线程等待5000毫秒,如果超过这个时间,则停止等待,变为可运行状态。
线程的加入join()对线程栈导致的结果是线程栈发生了变化,当然这些变化都是瞬时的。
下面给示意图:小结
到目前位置,介绍了线程离开运行状态的3种方法:
1、调用Thread.sleep():使当前线程睡眠至少多少毫秒(尽管它可能在指定的时间之前被中断)。
2、调用Thread.yield():不能保障太多事情,尽管通常它会让当前运行线程回到可运行性状态,使得有相同优先级的线程有机会执行。
3、调用join()方法:保证当前线程停止执行,直到该线程所加入的线程完成为止。
然而,如果它加入的线程没有存活,则当前线程不需要停止。
除了以上三种方式外,还有下面几种特殊情况可能使线程离开运行状态:
1、线程的run()方法完成。
2、在对象上调用wait()方法(不是在线程上调用)。
3、线程不能在对象上获得锁定,它正试图运行该对象的方法代码。
4、线程调度程序可以决定将当前运行状态移动到可运行状态,以便让另一个线程获得运行机会,而不需要任何理由。
一、同步问题提出
线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。
public class Foo {
private int x = 100;
public int getX() {
return x;
}
public int fix(int y) {
x = x - y;
return x;
}
}
public class MyRunnable implements Runnable {
private Foo foo = new Foo();
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread ta = new Thread(r, "Thread-A");
Thread tb = new Thread(r, "Thread-B");
ta.start();
tb.start();
}
public void run() {
for (int i = 0; i < 3; i++) {
this.fix(30);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
+ " : 当前foo对象的x值= " + foo.getX());
}
}
public int fix(int y) {
return foo.fix(y);
}
}
运行结果:
Thread-A : 当前foo对象的x值= 40
Thread-B : 当前foo对象的x值= 40
Thread-B : 当前foo对象的x值= -20
Thread-A : 当前foo对象的x值= -50
Thread-A : 当前foo对象的x值= -80
Thread-B : 当前foo对象的x值= -80
Process finished with exit code 0
从结果发现,这样的输出值明显是不合理的。
原因是两个线程不加控制的访问Foo对象并修改其数据所致。
如果要保持结果的合理性,只需要达到一个目的,就是将对Foo的访问加以限制,每次只能有一个线程在访问。
这样就能保证Foo对象中数据的合理性了。
在具体的Java代码中需要完成一下两个操作:
把竞争访问的资源类Foo变量x标识为private;
同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。