×

线程进程 进程 线程

什么是进程什么是线程他们之间有什么关系?求教高手:java中如何暂停一个线程中的任务,在以后的可以恢复之前任务的执行

admin admin 发表于2022-04-27 02:46:44 浏览157 评论0

抢沙发发表评论

什么是进程什么是线程他们之间有什么关系

什么是系统进程进程是指在系统中正在运行的一个应用程序;线程是系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元。对于操作系统而言,其调度单元是线程。一个进程至少包括一个线程,通常将该线程称为主线程。一个进程从主线程的执行开始进而创建一个或多个附加线程,就是所谓基于多线程的多任务。那进程与线程的区别到底是什么?进程是执行程序的实例。例如,当你运行记事本程序(Nodepad)时,你就创建了一个用来容纳组成Notepad.exe的代码及其所需调用动态链接库的进程。每个进程均运行在其专用且受保护的地址空间内。因此,如果你同时运行记事本的两个拷贝,该程序正在使用的数据在各自实例中是彼此独立的。在记事本的一个拷贝中将无法看到该程序的第二个实例打开的数据。以沙箱为例进行阐述。一个进程就好比一个沙箱。线程就如同沙箱中的孩子们。孩子们在沙箱子中跑来跑去,并且可能将沙子攘到别的孩子眼中,他们会互相踢打或撕咬。但是,这些沙箱略有不同之处就在于每个沙箱完全由墙壁和顶棚封闭起来,无论箱中的孩子如何狠命地攘沙,他们也不会影响到其它沙箱中的其他孩子。因此,每个进程就象一个被保护起来的沙箱。未经许可,无人可以进出。实际上线程运行而进程不运行。两个进程彼此获得专用数据或内存的唯一途径就是通过协议来共享内存块。这是一种协作策略。下面让我们分析一下任务管理器里的进程选项卡。这里的进程是指一系列进程,这些进程是由它们所运行的可执行程序实例来识别的,这就是进程选项卡中的第一列给出了映射名称的原因。请注意,这里并没有进程名称列。进程并不拥有独立于其所归属实例的映射名称。换言之,如果你运行5个记事本拷贝,你将会看到5个称为Notepad.exe的进程。它们是如何彼此区别的呢?其中一种方式是通过它们的进程ID,因为每个进程都拥有其独一无二的编码。该进程ID由WindowsNT或Windows2000生成,并可以循环使用。因此,进程ID将不会越编越大,它们能够得到循环利用。第三列是被进程中的线程所占用的CPU时间百分比。它不是CPU的编号,而是被进程占用的CPU时间百分比。此时我的系统基本上是空闲的。尽管系统看上去每一秒左右都只使用一小部分CPU时间,但该系统空闲进程仍旧耗用了大约99%的CPU时间。第四列,CPU时间,是CPU被进程中的线程累计占用的小时、分钟及秒数。请注意,我对进程中的线程使用占用一词。这并不一定意味着那就是进程已耗用的CPU时间总和,因为,如我们一会儿将看到的,NT计时的方式是,当特定的时钟间隔激发时,无论谁恰巧处于当前的线程中,它都将计算到CPU周期之内。通常情况下,在大多数NT系统中,时钟以10毫秒的间隔运行。每10毫秒NT的心脏就跳动一下。有一些驱动程序代码片段运行并显示谁是当前的线程。让我们将CPU时间的最后10毫秒记在它的帐上。因此,如果一个线程开始运行,并在持续运行8毫秒后完成,接着,第二个线程开始运行并持续了2毫秒,这时,时钟激发,请猜一猜这整整10毫秒的时钟周期到底记在了哪个线程的帐上?答案是第二个线程。因此,NT中存在一些固有的不准确性,而NT恰是以这种方式进行计时,实际情况也如是,大多数32位操作系统中都存在一个基于间隔的计时机制。请记住这一点,因为,有时当你观察线程所耗用的CPU总和时,会出现尽管该线程或许看上去已运行过数十万次,但其CPU时间占用量却可能是零或非常短暂的现象,那么,上述解释便是原因所在。上述也就是我们在任务管理器的进程选项卡中所能看到的基本信息列。什么是线程?究竟什么是线程呢?正如在图A中所示,一个线程是给定的指令的序列(你所编写的代码),一个栈(在给定的方法中定义的变量),以及一些共享数据(类一级的变量)。线程也可以从全局类中访问静态数据。栈以及可能的一些共享数据每个线程有其自己的堆栈和程序计数器(PC)。你可以把程序计数器(PC)设想为用于跟踪线程正在执行的指令,而堆栈用于跟踪线程的上下文,上下文是当线程执行到某处时,当前的局部变量的值。虽然你可以编写出在线程之间传送数据的子程序,在正常情况下,一个线程不能访问另外一个线程的栈变量。一个线程必须处于如下四种可能的状态之一,这四种状态为:初始态:一个线程调用了new方法之后,并在调用start方法之前的所处状态。在初始态中,可以调用start和stop方法。Runnable:一旦线程调用了start方法,线程就转到Runnable状态,注意,如果线程处于Runnable状态,它也有可能不在运行,这是因为还有优先级和调度问题。阻塞/NonRunnable:线程处于阻塞/NonRunnable状态,这是由两种可能性造成的:要么是因挂起而暂停的,要么是由于某些原因而阻塞的,例如包括等待IO请求的完成。退出:线程转到退出状态,这有两种可能性,要么是run方法执行结束,要么是调用了stop方法。最后一个概念就是线程的优先级,线程可以设定优先级,高优先级的线程可以安排在低优先级线程之前完成。一个应用程序可以通过使用线程中的方法setPriority(int),来设置线程的优先级大小。

求教高手:java中如何暂停一个线程中的任务,在以后的可以恢复之前任务的执行

可以用以下几种方法:interrupt():中断线程stop():强迫线程停止执行。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。yield()只能使同优先级的线程有执行的机会。----这句是重点 3.书上说yelid()是礼让,是让当前执行线程停下来给别的线程资源, 又说没有任何机制保证会这样。----------没有任何机制保证执行yield()的线程一定会把资源让给其它线程。打个比方:两个人抢东西,A抢到了B没有,再把东西放回去重抢,说不定还是A抢到B没有。没有任何机制保证放回去后B一定能抢到sleep方法使线程睡眠,但是到一定毫秒数时会自动到cpu中等待wait方法使线程等待,但是不会自动到cpu中等待,要通过notify或者notifyall方法进行唤醒。以上是让线程等待的方法,你可以选择适合你程序的方法。

windows怎么实现线程间的通信

Windows线程间通信.1.概述如果一个进程中的所有线程都不需要相互传递数据就可以顺利完成,那么程序运行的性能自然是最好的,但是实际上,很少有现成能够在所有的时间都独立的进行操作,通常在以下两种情况下,线程之间需要进行通信。a) 多个线程都对共享资源资源进行访问,但不希望共享资源被破坏。b) 一个线程完成了任务,要通知其他的线程。情况a)属于互斥问题,情况b)属于同步问题。通常的解决方法如下:2.解决方法a) 互锁函数互锁函数是windows提供的一个函数族,它可以实现对共享变量的简单原子访问,所谓的原子访问就是说当当前线程正在访问资源时,可以保证其他的线程没有同时访问这个资源。但是它只能完成以原子操作方式修改单个值,作用域很小。Eg:Long g = 0;DWORD _stdcall TF1(PVOID p){g++;Return 0;}DWORD _stdcall TF2(PVOID p){g++;Return 0;}在上面的例子中,不能保证运行结束时g的值为2,因为在自加的过程中,线程可能会被另一个线程打断,这时,两个线程可能对同一个变量进行了操作,出现了错误,这是使用互锁函数改为即可保证在一个线程进行g++时,另一个线程不会将其打断。Long g = 0;DWORD _stdcall TF1(PVOID p){InterlockedExchangeAdd(&g, 1);Return 0;}DWORD _stdcall TF2(PVOID p){InterlockedExchangeAdd(&g, 1);Return 0;}类似的函数还有LONG InterlockedExchange(PLONG plTarget, LONG lValue);PVOID InterlockedCompareExchange(PLONG plDestination, LONG lExchange, LONG lComparand);b) 临界段临界段也叫做关键代码段,它是一小段代码,通过设置临界区域,能够以原子操作的方式使用资源。具有相同临界资源的临界段只能允许一个线程执行它,其他要进入该段的线程将被挂起,直到前面的线程释放临界资源。Win32 API中临界段的设置:首先定义一个全局临界对象,类型为CRITICAL_SECTIONCRITICAL_SECTION cs;然后调用函数对其初始化:InitializeCriticalSection(&cs);这样就创建了一个名为cs的临界段对象了,然后对于可能会发生冲突的线程代码段使用同一个临界对象进行处理即可,进入临界段的代码为:EnterCriticalSection(&cs);此时,线程被认为拥有临界段对象,没有两个线程可以同时拥有相同的临界对象,因此,如果一个线程进入了临界段,那么下一个使用相同临界段对象调用EnterCriticalSection的线程将被挂起。离开临界段的函数为:LeaveCriticalSeciton(&cs);此时,释放临界对象的所有权,删除临界对象的函数为:DeleteCriticalSection(&cs);c) 使用内核对象进行线程通信互锁函数和临界段都是属于用户态的通信,好处是速度很快,但是对许多应用程序而言是不足的,而使用内核对象进行通信速度较慢,其他的性能较好。使用内核对象进行线程通信的机理是:很多内核对象存在一个属性,用来表示该内核对象是已通知状态还是未通知状态,然后通常使用WaitForSingleObject或WaitForMultipleObjects来等待特定内核对象的已通知状态。事件对象事件内核对象通常和WaitForSingleObject等联合使用,事件对象主要用于标志一个操作是否已经完成,其函数为:HANDLE CreateEvent(PSECURITY_ATTRIBUTES psa,BOOL fManualReset,BOOL fInitialState,PCTSTR pszName);第一个参数为安全属性,第二个参数用于设置创建一个人工重置事件(ture)还是自动重置事件,两者的区别在于:如果设置成人工重置事件,则需要使用SetEvent和ResetEvent函数来将事件设置成已通知事件和未通知事件,当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度的;如果设置成自动重置事件,当使用SetEvent设置事件的通知状态时,在等待事件的线程中,只有一个线程被回复(哪个不确定),之后系统自动将事件设为未通知状态。第三个参数用于设置事件初始状态,第四个参数用于设置事件的名字。互斥对象互斥量是一种内核对象,它能够确保线程拥有对单个资源的互斥访问权。它与临界段相同,但是互斥量属于内核对象,临界段属于用户对象,这意味着互斥要比临界段慢,但是不同进程中的多个线程能够访问单个互斥量。互斥量不同于所有其他的内核对象,互斥量中有一个线程ID,用于标志该互斥量属于哪个线程(即不论在哪个线程中创建了没有归属的互斥量,只要在某个线程中将互斥量变为未通知事件,那么这个线程就拥有这个互斥量,如果在该线程中释放了这个互斥量,那么该互斥量又变成游离状态,没有所属的线程,然后重复上面的过程),因此互斥量有一个“线程所有权”的概念,因此如果调用ReleaseMutex的线程不拥有互斥量,那么该函数不进行任何操作。Win32 API互斥量函数:创建一个互斥量:HANDLE CreateMutex(PSECURITY_ATTRIBUTES psa,BOOL fInitialOwner,PCTSTR pszName);第一个参数安全属性,最后一个参数为互斥量的名字,第二个参数:A) 如果设为FALSE,则表示没有线程拥有该互斥量,线程ID为0,处于已通知 状态。B) 如果设为TURE,则表示当前线程拥有该互斥,线程ID为当前线程的ID,处 于未通知状态。当某个拥有互斥的线程不想再拥有该互斥的时候,则调用函数:ReleaseMutex(HANDLE hMutex);来释放该线程对该互斥的占有,此后该互斥量又变成游离的状态,直到再出现一个 线程拥有它。信号量信号量也是一种内核对象,用于对资源进行计数。信号量的使用规则是:如果当前资源数量大于0,那么等待信号量的线程可以获得一个资源并继续执行,信号量的当前资源数将减1;如果当前资源数为0,那么等待信号量的线程将处于等待状态,直到有线程释放信号量,使当前资源数大于0,当前资源数不会超过最大资源数量值,也不会小于0。Win32用于创建和释放信号量的API函数HANDLE CreateSemaphore(PSECURITY_ATTRIBUTE psa,LONG lInitialCount,LONG lMaximumCount,PCTSTR pszName);BOOL ReleaseSemaphore(HANDLE hsem,LONG lReleaseCount,PLONG plPreviousCount);参考链接: