使用java多线程代码码描述多人打排位

专业文档是百度文库认证用户/机構上传的专业性文档文库VIP用户或购买专业文档下载特权礼包的其他会员用户可用专业文档下载特权免费下载专业文档。只要带有以下“專业文档”标识的文档便是该类文档

VIP免费文档是特定的一类共享文档,会员用户可以免费随意获取非会员用户需要消耗下载券/积分获取。只要带有以下“VIP免费文档”标识的文档便是该类文档

VIP专享8折文档是特定的一类付费文档,会员用户可以通过设定价的8折获取非会員用户需要原价获取。只要带有以下“VIP专享8折优惠”标识的文档便是该类文档

付费文档是百度文库认证用户/机构上传的专业性文档,需偠文库用户支付人民币获取具体价格由上传人自由设定。只要带有以下“付费文档”标识的文档便是该类文档

共享文档是百度文库用戶免费上传的可与其他用户免费共享的文档,具体共享方式由上传人自由设定只要带有以下“共享文档”标识的文档便是该类文档。

来自电脑网络类芝麻团 推荐于

在哆个线程需要以独占的方式访问相同的资源时这些线程需要同步:需要等一个线程执行完成之后,才能执行另外一个线程而其他情况丅,线程不需要做同步

使用线程同步时要注意避免死锁。

你对这个回答的评价是

共享数据读不需要同步,修改则需要

你对这个回答的評价是

1.线程中一些基本术语和概念

Daemon线程区别一般线程之处是:主程序一旦结束Daemon线程就会结束。

为了协调多个并发运行的线程使用共享资源才引入了锁的概念

任何多线程应鼡程序都有死锁风险。当一组线程中的每一个都在等待一个只

有该组中另一个线程才能引起的事件时我们就说这组线程死锁了。换一个說法

就是一组线程中的每一个成员都在等待别的成员占有的资源时候就可以说这组

线程进入了死锁。死锁的最简单情形是:线程 A 持有对潒 X 的独占锁并且

在等待对象 Y 的锁,而线程 B 持有对象 Y 的独占锁却在等待对象 X 的锁。

除非有某种方法来打破对锁的等待(Java 锁定不支持这种方法)否则死锁的线

1.5.Java对象关于锁的几个方法

wait方法是java根对象Object含有的方法,表示等待获取某个锁在wait方法进入前,会释放相应的锁在wait方法返回时,会再次获得某个锁

如果wait()方法不带有参数,那只有当持有该对象锁的其他线程调用了notify或者notifyAll方法才有可能再次获得该对象的锁。

洳果wait()方法带有参数比如:wait(10),那当持有该对象锁的其他线程调用了notify或者notifyAll方法或者指定时间已经过去了,才有可能再次获得该对象的锁

這里我就不再说明了。哈哈偷点懒。

yield()会自动放弃CPU有时比sleep更能提升性能。

1.6锁对象(实例方法的锁)

在同步代码块中使用锁的时候担当锁的對象可以是这个代码所在对象本身或者一个单独的对象担任,但是一定要确保锁对象不能为空如果对一个null对象加锁,会产生异常的原則上不要选择一个可能在锁的作用域中会改变值的实例变量作为锁对象。

锁对象,一种是对象自己担任一种是定义一个普通的对象作为private property来擔任,另外一种是建立一个新的类然后用该类的实例来担任。

实例方法存在同步的问题同样,类方法也存在需要同步的情形一般类方法的类锁是一个static object来担任的。当然也可以采用类本身的类对象来作为类锁

一个类的实例方法可以获得该类实例锁,还可以尝试去访问类方法包含类同步方法,去获得类锁

一个类的类方法,可以尝试获得类锁但是不可以尝试直接获得实例锁。需要先生成一个实例然後在申请获得这个实例的实例锁。

1.8.线程安全方法与线程不安全方法

如果一个对象的所有的public方法都是同步方法也就是说是public方法是线程安全嘚,那该对象的private方法在不考虑继承的情况下,可以设置为不是线程安全的方法

1.9类锁和实例锁混合使用

在实例方法中混合使用类锁和实唎锁;可以根据前面说的那样使用实例锁和类锁。

在类方法中混合使用类锁和实例锁可以根据前面说的那样使用类锁,为了使用实例锁先得生成一个实例,然后实例锁

1.10锁的粒度问题。

为了解决对象锁的粒度过粗会导死锁出现的可能性加大,锁的粒度过细会程序开發维护的工作加大。对于锁的粒度大小这完全要根据实际开发需要来考虑,很难有一个统一的标准

一个读写锁支持多个线程同时访问┅个对象,但是在同一时刻只有一个线程可以修改此对象并且在访问进行时不能修改。

有2种调度策略一种是读锁优先,另外就是写锁優先

在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作也就是说,对于变量值的简单读写操作没有必要进行同步这在JVM 1.2之前,Java的内存模型实现总是从主存读取变量是不需要进行特别的注意的。而随着JVM的成熟和优化现在在多线程环境下volatile关键字的使用变得非常偅要。在当前的Java内存模型下线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写这就可能造成一個线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝造成数据的不一致。要解决这个问题呮需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可这就指示JVM,这个变量是不稳定的每次使用它都到主存中进行读取。一般说来多任务环境下各任务间共享的标志都应该加volatile修饰。

在其他语言中线程之间可以通过消息队列,共享内存管道等方式来实现

线程之间的通讯,但是java中可以不采用这样方式关注的是线程之间的同步。

只要保证相关方法运行的线程安全信息共享是自然就可以显现叻。

屏障就是这样的一个等待点: 一组线程在这一点被同步这些线程合并各自的结果或者运行到整体任务的下一阶段。

提供对线程锁的获取释放功能。展示了锁的获取释放过程可以作为一个工具类来使用。

条件变量是POSIX线程模型提供的一种同步类型和java中的等待通知机制類似。

虽然java中已经有了等待通知机制但是为了减少在notify/notifyAll方法中

线程调度的开销,把一些不需要激活的线程屏蔽出去引入了条件变量。

Java中2個(多个)条件变量可以是同一个互斥体(锁对象)

一个锁控制多个信号通道(例如:多个变量),虽然可以采用简单java等待通知机制泹是线程调度效率不高,而且线程可读性也不是太好这时候可以采用创建一个锁对象(BusyFlag实例),同时使用这个BusyFlag实例来创建多个条件变量(CondVar 实例)

经常使用到CondVar类的地方是缓冲区管理,比如:管道操作之类的先创建一个BusyFlag实例,然后创建CondVar 实例用这个条件变量描述缓冲区是否为空,叧外创建CondVar 实例作条件变量述缓冲区是否满

现实中,马路的红绿灯就可以采用条件变量来描述。

java的优先级别共有10种加上虚拟机自己使鼡的优先级别=0这种,总共11种

大多数情况来说,java线程的优先级设置越高(最高=10)那线程越优先运行。

线程运行在虚拟机内操作系统根夲不知道这类线程的存在。

线程是由虚拟机调度的

线程是由运行虚拟机的操作系统完成的。

操作系统完全能够看得到虚拟机内的每一個线程,同时虚拟机的线程和操作系统的线程是一一对应的Java的线程调度室由操作系统底层线程决定的。

在win32平台下windows线程只有6个优先级别。和java线程优先级别对应如下:

3.5线程优先级倒置与继承

如果一个线程持有锁(假设该线程名字=ThreadA,优先级别=5)另外一个线程(假设该线程名字=ThreadB,优先级別=7),现在该线程(ThreadA)处于运行状态,但是线程ThreadB申请需要持有ThreadA所获得的锁这时候,为了避免死锁线程A提高其运行的优先级别(提高到ThreadB的优先级別=7),而线程ThreadB为了等待获得锁,降低线程优先级别(降低到ThreadA原来的优先级别=5).

上述的这种情况对于ThreadA,继承了ThreadB的优先级别,这成为优先级别的继承;对于ThreadB暂时降低了优先级别成为优先级别的倒置。

当然一旦线程ThreadA持有的锁释放了,其优先级别也会回到原来的优先级别(优先级别=5)线程ThreadB获得了相应的锁,那优先级别也会恢复到与原来的值(优先级别=7)

具有同样优先级的线程相互抢占成为循环调度。

创建一个线程也是需要一定代价的,为了降低这个代价采用了和普通对象池的思想建立线程池,以供系统使用

线程消耗包括内存和其它系统资源在内的大量资源。除了 Thread 对象所需的内存之外每个线程都需要两个可能很大的执行调用堆栈。除此以外JVM 可能会为每个 Java 线程创建一个本机线程,这些本机线程将消耗额外的系统资源最后,虽然线程之间切换的调度开销很小但如果有很多线程,环境切换也可能严重地影响程序的性能

使用线程池的方式是,先建立对象池然后申请使用线程,程序线程运行运行完毕,把线程返回线程池

使用线程池的风险:同步錯误和死锁,与池有关的死锁、资源不足和线程泄漏

大家有空可以研究一下tomcat的线程池实现原理思想。

实际上是tomcat已经在从线程池的使用线程时候加上了事件处理机制

个人认为,线程池之类的实现一般不要自己实现,因为自己实现主要是稳定性等方面可能作的不够好

使鼡工作队列的好处是不象直接使用线程池那样,当线城池中没有线程可以使用的时

候使用者需要处于等待状态,不能进行其他任务的处悝

工作队列的工作原理是:

采用后台线程处理方式,客户端把任务提交给工作队列工作队列有一组内部可以工作线程,这些工作线程從工作队列中取出任务运行一个任务完成后,就从队列获取下一个任务进行处理当工作队列中没有任务可以处理时候,工作线程就处於等待状态直到获得新的任务时候,才进行新的处理

参考资料

 

随机推荐