文章编号:11436时间:2024-09-30人气:
在 Java 中,
suspendThread
方法曾用于暂停线程的执行。由于存在许多缺点,该方法已于 JDK 9 中被弃用。
本文将介绍一种更现代的线程同步机制——线程同步屏障(barrier),它提供了类似于
suspendThread
的暂停线程功能,但具有更好的可靠性和安全性。
线程同步屏障是一种同步原语,它允许线程组中的所有线程等待,直到所有线程都到达指定屏障点。
线程同步屏障有以下特点:
要使用线程同步屏障,需要创建
CyclicBarrier
对象。
CyclicBarrier
的构造函数需要一个整数参数,表示要等待的线程数。
每个线程都可以调用
await()
方法来等待屏障点。当所有线程都调用了
await()
方法,屏障点将被解除,所有线程将继续执行。
以下代码示例展示了如何使用线程同步屏障:
import java.util.concurrent.CyclicBarrier;public class ThreadSyncBarrierExample {public static void main(String[] args) {
// 创建一个CyclicBarrier对象,等待5个线程CyclicBarrier barrier = new CyclicBarrier(5);// 创建5个线程并启动它们for (int i = 0; i < 5; i++) {new Thread(() -> {try {// 线程等待屏障点barrier.await();// 屏障点被解除后,继续执行System.out.println("线程 " + Thread.currentThread().getName() + " 已通过屏障点");} catch (Exception e) {e.printStackTrace();}}).start();}}}
线程同步屏障比
suspendThread
具有以下优点:
suspendThread
可能会导致死锁,而线程同步屏障不会。
suspendThread
可以在任何时候被中断。
suspendThread
的释放顺序是不确定的。
线程同步屏障还提供了更多高级功能,例如超时和中断机制,这使得它在对线程控制有更严格要求的场景中更加有用。
线程同步屏障是一种更现代、更安全的替代方案,用于替代弃用的
suspendThread
方法。它提供了一致且可预测的线程同步机制,非常适合需要精确控制线程执行顺序的场景。
这个函数是主要用于调试器。 它并不打算用于线程同步。 在一个线程调用SuspendThread拥有一个同步对象,比如互斥或关键部分,会导致死锁如果调用线程试图获取同步对象属于一个暂停的线程。 为了避免这种情况,一个线程在一个应用程序,它不是一个调试器应该信号其他线程暂停本身
暂停线程执行的API函数是SuspendThread,声明如下:DWORD SuspendThread(HANDLEhThread);其中,参数hThread是要暂停的线程句柄,该句柄必须要有THREAD SUSPEND RESUME访问权限。 如果函数成功就返回以前暂停的次数,否则返回-1,此时可以用GetLastError来获得错误码。 当函数成功的时候,线程将暂停执行,并且线程的暂停次数递增一次。 每个线程都有一个暂停计数器,最大值为MAXIMUMSUSPENDCOUNT,如果暂停计数器大于零,线程则暂停执行。 另外,这个函数一般不用于线程同步,如果对一个拥有同步对象(比如信号量或临界区)的线程调用SuspendThread函数,则有可能会引起死锁,尤其当被暂停的线程想要获取同步对象的时候。 恢复线程执行的函数是ResumeThread,但不是说调用该函数线程就会恢复执行,该函数主要是减少暂停计数器的次数。 线程的暂停计数器如果恢复到零,线程才会恢复执行。 暂停线程执行的API函数是SuspendThread,声明如下:DWORD SuspendThread(HANDLEhThread);其中,参数hThread是要暂停的线程句柄,该句柄必须要有THREAD SUSPEND RESUME访问权限。 如果函数成功就返回以前暂停的次数,否则返回-1,此时可以用GetLastError来获得错误码。 当函数成功的时候,线程将暂停执行,并且线程的暂停次数递增一次。 每个线程都有一个暂停计数器,最大值为MAXIMUMSUSPENDCOUNT,如果暂停计数器大于零,线程则暂停执行。 另外,这个函数一般不用于线程同步,如果对一个拥有同步对象(比如信号量或临界区)的线程调用SuspendThread函数,则有可能会引起死锁,尤其当被暂停的线程想要获取同步对象的时候。 恢复线程执行的函数是ResumeThread,但不是说调用该函数线程就会恢复执行,该函数主要是减少暂停计数器的次数。 线程的暂停计数器如果恢复到零,线程才会恢复执行。
在windows下做服务器最好的方案是IOCP(I/O Complete port),中文名I/O完成端口性能很不错。 涉及windows高级编程,难学指数比较高你的的感觉很不错,这个方案不可行:1.会浪费大量CPU时间。 一台计算机CPU个数有限,如果你的计算机只有2个CPU,却开了200线程。 这个时候在同一时间,最多有2个线程在运行(因为你只有2个CPU),但是线程的不断切换让你感觉好像200个都在运行,只不过速度很慢。 (此时线程切换会耗掉大量CPU时间,得不偿失)。 2.浪费内存。 线程在windows中需要用数据表示,200个线程,开销有点浪费(虽然现在内存都很大,但是我们不能浪费)3.线程同步问题会让你晕掉的,200个线程并发处理是很麻烦的,要进行线程同步,以及线程通信,同步和通信是多线程必须深思熟虑的。 4.有一个很不错的解决方案---IOCP关于IOCP的学习,网上资料很多在此不多言。 enjoy coding
线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源、什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些原则问题需要考虑,是否有竞争资源被同时改动的问题?对于同步,在具体的Java代码中需要完成以下两个操作:把竞争访问的资源标识为private;同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
当然这不是唯一控制并发安全的途径。
synchronized关键字使用说明synchronized只能标记非抽象的方法,不能标识成员变量。
为了演示同步方法的使用,构建了一个信用卡账户,起初信用额为100w,然后模拟透支、存款等多个操作。
显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,禁止直接访问。
工作原理线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。
线程不拥有系统资源,只有运行必须的一些数据结构;它与父进程的其它线程共享该进程所拥有的全部资源。
线程可以创建和撤消线程,从而实现程序的并发执行。
一般,线程具有就绪、阻塞和运行三种基本状态。
在多中央处理器的系统里,不同线程可以同时在不同的中央处理器上运行,甚至当它们属于同一个进程时也是如此。
大多数支持多处理器的操作系统都提供编程接口来让进程可以控制自己的线程与各处理器之间的关联度(affinity)。
有时候,线程也称作轻量级进程。
就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。
但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。
它们共享内存、文件句柄和其它每个进程应有的状态。
进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。
一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。
尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。
Java 线程工具和 API看似简单。
但是,编写有效使用线程的复杂程序并不十分容易。
因为有多个线程共存在相同的内存空间中并共享相同的变量,所以您必须小心,确保您的线程不会互相干扰。
线程属性为了正确有效地使用线程,必须理解线程的各个方面并了解Java 实时系统。
必须知道如何提供线程体、线程的生命周期、实时系统如 何调度线程、线程组、什么是幽灵线程(Demo nThread)。
线程体所有的操作都发生在线程体中,在Java中线程体是从Thread类继承的run()方法,或实现Runnable接口的类中的run()方法。
当线程产生并初始化后,实时系统调用它的run()方法。
run()方法内的代码实现所产生线程的行为,它是线程的主要部分。
线程状态附图表示了线程在它的生命周期内的任何时刻所能处的状态以及引起状态改变的方法。
这图并不是完整的有限状态图,但基本概括了线程中比较感兴趣和普遍的方面。
以下讨论有关线程生命周期以此为据。
●新线程态(New Thread)产生一个Thread对象就生成一个新线程。
当线程处于新线程状态时,仅仅是一个空线程对象,它还没有分配到系统资源。
因此只能启动或终止它。
任何其他操作都会引发异常。
例如,一个线程调用了new方法之后,并在调用start方法之前的处于新线程状态,可以调用start和stop方法。
●可运行态(Runnable)start()方法产生运行线程所必须的资源,调度线程执行,并且调用线程的run()方法。
在这时线程处于可运行态。
该状态不称为运行态是因为这时的线程并不总是一直占用处理机。
特别是对于只有一个处理机的PC而言,任何时刻只能有一个处于可运行态的线程占用处理 机。
Java通过调度来实现多线程对处理机的共享。
注意,如果线程处于Runnable状态,它也有可能不在运行,这是因为还有优先级和调度问题。
●阻塞/非运行态(Not Runnable)当以下事件发生时,线程进入非运行态。
①suspend()方法被调用;②sleep()方法被调用;③线程使用wait()来等待条件变量;④线程处于I/O请求的等待。
●死亡态(Dead)当run()方法返回,或别的线程调用stop()方法,线程进入死亡态。
通常Applet使用它的stop()方法来终止它产生的所有线程。
线程的本操作:派生:线程在进程内派生出来,它即可由进程派生,也可由线程派生。
阻塞(Block):如果一个线程在执行过程中需要等待某个事件发生,则被阻塞。
激活(unblock):如果阻塞线程的事件发生,则该线程被激活并进入就绪队列。
调度(schedule):选择一个就绪线程进入执行状态。
结束(Finish):如果一个线程执行结束,它的寄存器上下文以及堆栈内容等将被释放。
图2 线程的状态与操作线程的另一个执行特性是同步。
线程中所使用的同步控制机制与进程中所使用的同步控制机制相同。
线程优先级虽然我们说线程是并发运行的。
然而事实常常并非如此。
正如前面谈到的,当系统中只有一个CPU时,以某种顺序在单CPU情况下执行多线程被称为调度(scheduling)。
Java采用的是一种简单、固定的调度法,即固定优先级调度。
这种算法是根据处于可运行态线程的相对优先级来实行调度。
当线程产生时,它继承原线程的优先级。
在需要时可对优先级进行修改。
在任何时刻,如果有多条线程等待运行,系统选择优先级最高的可运行线程运行。
只有当它停止、自动放弃、或由于某种原因成为非运行态低优先级的线程才能运行。
如果两个线程具有相同的优先级,它们将被交替地运行。
Java实时系统的线程调度算法还是强制性的,在任何时刻,如果一个比其他线程优先级都高的线程的状态变为可运行态,实时系统将选择该线程来运行。
一个应用程序可以通过使用线程中的方法setPriority(int),来设置线程的优先级大小。
有线程进入了就绪状态,需要有线程调度程序来决定何时执行,根据优先级来调度。
线程中的join()可以用来邀请其他线程先执行(示例代码如下);publicclassJoin01implementsRunnable{publicstaticvoidmain(String[]args){for(inti=0;i<20;i++){if(i==5){Join01j=newJoin01();Threadt=newThread(j);(被邀请先执行的线程.);();try{//邀请这个线程,先执行();}catch(InterruptedExceptione){();}}(没被邀请的线程。
+(i+1));}}publicvoidrun(){for(inti=0;i<10;i++){(()()+(i+1));}}}yield()告诉系统把自己的CPU时间让掉,让其他线程或者自己运行,示例代码如下;publicclassYield01{publicstaticvoidmain(String[]args){YieldFirstyf=newYieldFirst();YieldSecondys=newYieldSecond();YieldThirdyt=newYieldThird();();();();}}classYieldFirstextendsThread{@Overridepublicvoidrun(){for(inti=0;i<10;i++){(第一个线程第+(i+1)+次运行.);//让当前线程暂停yield();}}}classYieldSecondextendsThread{@Overridepublicvoidrun(){for(inti=0;i<10;i++){(第二个线程第+(i+1)+次运行.);//让当前线程暂停yield(); ,仅适用于Sun Solaris操作系统。
所以UNIX International线程也常被俗称为Solaris线程。
1.创建线程intthr_create(void*stack_base,size_tstack_size,void*(*start_routine)(void*),void*arg,longflags,thread_t*new_thr);2.等待线程intthr_join(thread_twait_for,thread_t*dead,void**status);3.挂起线程intthr_suspend(thread_tthr);4.继续线程intthr_continue(thread_tthr);5.退出线程voidthr_exit(void*status);6.返回当前线程的线程标识符thread_tthr_self(void);POSIX线程POSIX线程(Pthreads)的头文件是
内容声明:
1、本站收录的内容来源于大数据收集,版权归原网站所有!
2、本站收录的内容若侵害到您的利益,请联系我们进行删除处理!
3、本站不接受违法信息,如您发现违法内容,请联系我们进行举报处理!
4、本文地址:http://www.jujiwang.com/article/e8693fa6a7b84d79f3a0.html,复制请保留版权链接!
简介Silverlight是一种Microsoft开发的跨浏览器、跨平台插件,用于创建丰富的、交互式的Web应用程序,它基于.NETFramework,并提供一系列功能来增强网站用户体验,Silverlight网站开发的优势丰富而生动的用户界面,Silverlight支持3D图形、动画、视频和音频,能够创建引人入胜的、沉浸式的用户界面...。
互联网资讯 2024-09-30 02:34:16
简介HttpClientJar是一个Java库,用于管理HTTPCookie和会话,它提供了一个统一的界面来处理不同类型的HTTP库中的Cookie和会话,使其成为管理HTTP会话的宝贵工具,安装HttpClientJar可以通过MavenCentral仓库进行安装,```xmlcom.github.daniel,shuyhttpcl...。
技术教程 2024-09-26 18:15:44
数学长期以来一直是科学和技术进步的基础,但传统数学存在一定的局限性,数栈是一种革命性的数字系统,它超越了这些限制,为数学开辟了新的可能性,数栈的原理数栈是由数学家约翰·康威在1980年代发明的,是一种基于堆栈的数学系统,每个数栈都是一个有序的数学对象的序列,这些对象可以是数字、函数或其他数学结构,数栈的基本操作是压栈,push,和出栈...。
互联网资讯 2024-09-26 01:54:04
文章内容...文章内容...文章内容...小标题1小标题1相关的内容...小标题1相关的内容...小标题2小标题2相关的内容...小标题2相关的内容...示例列表列表项1列表项2列表项3示例表格表头1表头2表头3单元格1,1单元格1,2单元格1,3单元格2,1单元格2,2单元格2,3示例代码块代码块内容...示例引用引文内容......。
本站公告 2024-09-24 01:55:33
OSGi,开放服务网关倡议,是一个用于开发模块化、可重用的Java组件的标准,它为构建可灵活扩展和适应不断变化需求的复杂系统提供了框架,OSGi的优势模块化,OSGi组件可以独立开发和部署,从而提高代码可重用性和维护性,可扩展性,OSGi架构允许动态添加和移除组件,而无需重新启动整个系统,松散耦合,OSGi组件通过服务接口松散耦合,促...。
技术教程 2024-09-23 14:27:46
简介在Web开发中,下拉列表,DropdownList,是一种常见的控件,允许用户从一系列预定义选项中选择一个,当用户与下拉列表交互时,会触发各种事件,理解这些事件并对其进行恰当处理对于创建响应式且易于使用的Web应用程序至关重要,事件类型以下是在使用下拉列表时会触发的事件,SelectedIndexChanged,当用户更改下拉列表...。
最新资讯 2024-09-15 15:25:42
什么是内连接,内连接是一种SQL连接,用于从两个表中选择满足特定条件的行,它仅返回两个表中具有匹配行的记录,所有其他行都会被忽略,内连接的陷阱1.丢失行内连接最常见的陷阱是丢失行,当连接条件不满足时,内连接将过滤掉整个行,即使该行在其他表中可能存在匹配项,这可能导致丢失重要数据,SELECTFROMtable1INNERJOINtab...。
最新资讯 2024-09-14 22:46:06
分布式锁在分布式系统中,多个进程或线程可能试图同时访问共享资源,这可能导致数据损坏或其他问题,为了防止这种情况,我们可以使用分布式锁,分布式锁是一种机制,它允许进程或线程获取对共享资源的独占访问权,一旦进程或线程获得了锁,它就可以访问资源,而其他进程或线程将被阻止访问,有许多不同的分布式锁实现方式,最常见的方法之一是使用分布式协调服务...。
技术教程 2024-09-10 19:10:10
什么是织梦之家,织梦之家是织梦内容管理系统,CMS,的官方网站,为织梦用户提供全面的服务和支持,织梦之家有哪些服务,官方论坛,提供技术支持、使用技巧交流和社区互动,技术文档,详细的织梦系统使用说明和技术文档,插件市场,丰富的织梦插件和模版资源,在线课程,专业的织梦系统教程和培训,官方微博,发布最新动态、产品信息和行业资讯,织梦之家可以...。
最新资讯 2024-09-09 21:50:31
在电子商务网站上,客户经常需要刷新页面才能看到更新后的信息,例如购物车中的商品数量或价格的变化,这通常是一个令人沮丧的过程,特别是当客户正在赶时间或尝试完成购买的时候,幸运的是,使用JavaScript,我们可以进行无痛刷新,可以瞬间更新页面,而无需客户刷新,这可以极大地提高客户体验,并有助于提高转化率,如何进行无痛刷新要实现无痛刷新...。
本站公告 2024-09-09 14:06:30
Oracle数据库是业界领先的关系型数据库管理系统,广泛用于各种规模的组织,无论你是初学者还是经验丰富的数据库专业人员,本指南将提供一个全面的分步指南,指导你下载和安装Oracle数据库,对于初学者第1步,访问Oracle下载页面在浏览器中访问Oracle技术网络,OTN,网站,https,www.oracle.com,techn...。
技术教程 2024-09-09 08:23:42
Java接口概述Java接口是一种抽象类型,它定义了一组方法签名,但不包含任何实现,接口用于为类指定契约,而无需指定其实现细节,接口在Java中扮演着至关重要的角色,它们提供了一种实现抽象和解耦的方法,通过强制类实现接口,您可以确保它们提供特定功能,而无需关心这些功能是如何实现的,接口的优点抽象,接口允许您创建抽象类层次结构,其中子类...。
本站公告 2024-09-08 12:30:22