实战篇(一)
在进入实战篇以前,我们简单说一下多线程编程的一般原则.
[安全性]是多线程编程的首要原则,如果两个以上的线程访问同一对象时,一个线程会损坏
另一个线程的数据,这就是违反了安全性原则,这样的程序是不能进入实际应用的.
安全性的保证可以通过设计安全的类和程序员的手工控制.如果多个线程对同一对象访问不
会危及安全性,这样的类就是线程安全的类,在JAVA中比如String类就被设计为线程安全的类.
而如果不是线程安全的类,那么就需要程序员在访问这些类的实例时手工控制它的安全性.
[可行性]是多线程编程的另一个重要原则,如果仅仅实现了安全性,程序却在某一点后不能继
续执行或者多个线程发生死锁,那么这样的程序也不能作为真正的多线程程序来应用.
相对而言安全性和可行性是相互抵触的,安全性越高的程序,可性行会越低.要综合平衡.
[高性能]多线程的目的本来就是为了增加程序运行的性能,如果一个多线程完成的工作还不
如单线程完成得快.那就不要应用多线程了.
高性能程序主要有以下几个方面的因素:
数据吞吐率,在一定的时间内所能完成的处理能力.
响应速度,从发出请求到收到响应的时间.
容量,指同时处理雅致同任务的数量.
安全性和可行性是必要条件,如果达到不这两个原则那就不能称为真正的多线程程序.
而高性是多线程编程的目的,也可以说是充要条件.否则,为什么采用多线程编程呢?
[生产者与消费者模式]
首先以一个生产者和消费者模式来进入实战篇的第一节.
生产者和消费者模式中保护的是谁?
多线程编程都在保护着某些对象,这个些对象是"紧俏资源",要被最大限度地利用,这也是
采用多线程方式的理由.在生产者消费者模式中,我们要保护的是"仓库",在我下面的这个例子中,
就是桌子(table)
我这个例子的模式完全是生产者-消费者模式,但我换了个名字.厨师-食客模式,这个食
堂中只有1张桌子,同时最多放10个盘子,现在有4个厨师做菜,每做好一盘就往桌子上放(生产者将
产品往仓库中放),而有6个食客不停地吃(消费者消费产品,为了说明问题,他们的食量是无限的).
一般而言,厨师200-400ms做出一盘菜,而食客要400-600ms吃完一盘.当桌子上放满了10
个盘子后,所有厨师都不能再往桌子上放,而当桌子是没有盘子时,所有的食客都只好等待.
下面我们来设计这个程序:
因为我们不知道具体是什么菜,所以叫它food:
classFood{}
然后是桌子,因为它要有序地放而且要有序地取(不能两个食客同时争取第三盘菜),所以我们
扩展LinkedList,或者你用聚合把一个LinkedList作为属性也能达到同样的目的,例子中我是用
继承,从构造方法中传入一个可以放置的最大值
classTableextendsjava.util.LinkedList{
intmaxSize;
publicTable(intmaxSize){
this.maxSize=maxSize;
}
}
现在我们要为它加两个方法,一是厨师往上面放菜的方法,一是食客从桌子上拿菜的方法.
放菜:因为一张桌子由多个厨师放菜,所以厨师放菜的要被同步,如果桌子上已经有十盘菜了.所有厨师
就要等待:
publicsynchronizedvoidputFood(Foodf){
while(this.size()>=this.maxSize){
try{
this.wait();
}catch(Exceptione){}
}
this.add(f);
notifyAll();
}
拿菜:同上面,如果桌子上一盘菜也没有,所有食客都要等待:
publicsynchronizedFoodgetFood(){
while(this.size()<=0){
try{
this.wait();
}catch(Exceptione){}
}
Foodf=(Food)this.removeFirst();
notifyAll();
returnf;
}
厨师类:
由于多个厨师要往一张桌子上放菜,所以他们要操作的桌子应该是同一个对象,我们从构造
方法中将桌子对象传进去以便控制在主线程中只产生一张桌子.
厨师做菜要用一定的时候,我用在make方法中用sleep表示他要消耗和时候,用200加上200的随机数保
证时间有200-400ms中.做好后就要往桌子上放.
这里有一个非常重要的问题一定要注意,就是对什么范围同步的问题,因为产生竞争的是桌子,所以所
有putFood是同步的,而我们不能把厨师自己做菜的时间也放在同步中,因为做菜是各自做的.同样食客
吃菜的时候也不应该同步,只有从桌子中取菜的时候是竞争的,而具体吃的时候是各自在吃.
所以厨师类的代码如下:
classChefextendsThread{
Tablet;
Randomr=newRandom(12345);
publicChef(Tablet){
this.t=t;
}
publicvoidrun(){
while(true){
Foodf=make();
t.putFood(f);
}
}
privateFoodmake(){
try{
Thread.sleep(200+r.nextInt(200));
}catch(Exceptione){}
returnnewFood();
}
}
同理我们产生食客类的代码如下:
classEaterextendsThread{
Tablet;
Randomr=newRandom(54321);
publicEater(Tablet){
this.t=t;
}
publicvoidrun(){
while(true){
Foodf=t.getFood();
eat(f);
}
}
privatevoideat(Foodf){
try{
Thread.sleep(400+r.nextInt(200));
}catch(Exceptione){}
}
}
完整的程序在这儿:
packagedebug;
importjava.util.regex.*;
importjava.util.*;
classFood{}
classTableextendsLinkedList{
intmaxSize;
publicTable(intmaxSize){
this.maxSize=maxSize;
}
publicsynchronizedvoidputFood(Foodf){
while(this.size()>=this.maxSize){
try{
this.wait();
}catch(Exceptione){}
}
this.add(f);
notifyAll();
}
publicsynchronizedFoodgetFood(){
while(this.size()<=0){
try{
this.wait();
}catch(Exceptione){}
}
Foodf=(Food)this.removeFirst();
notifyAll();
returnf;
}
}
classChefextendsThread{
Tablet;
Stringname;
Randomr=newRandom(12345);
publicChef(Stringname,Tablet){
this.t=t;
this.name=name;
}
publicvoidrun(){
while(true){
Foodf=make();
System.out.println(name+"putaFood:"+f);
t.putFood(f);
}
}
privateFoodmake(){
try{
Thread.sleep(200+r.nextInt(200));
}catch(Exceptione){}
returnnewFood();
}
}
classEaterextendsThread{
Tablet;
Stringname;
Randomr=newRandom(54321);
publicEater(Stringname,Tablet){
this.t=t;
this.name=name;
}
publicvoidrun(){
while(true){
Foodf=t.getFood();
System.out.println(name+"getaFood:"+f);
eat(f);
}
}
privatevoideat(Foodf){
try{
Thread.sleep(400+r.nextInt(200));
}catch(Exceptione){}
}
}
publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
Tablet=newTable(10);
newChef("Chef1",t).start();
newChef("Chef2",t).start();
newChef("Chef3",t).start();
newChef("Chef4",t).start();
newEater("Eater1",t).start();
newEater("Eater2",t).start();
newEater("Eater3",t).start();
newEater("Eater4",t).start();
newEater("Eater5",t).start();
newEater("Eater6",t).start();
}
}
这一个例子中,我们主要关注以下几个方面:
1.同步方法要保护的对象,本例中是保护桌子,不能同时往上放菜或同时取菜.
假如我们把putFood方法和getFood方法在厨师类和食客类中实现,那么我们应该如此:
(以putFood为例)
classChefextendsThread{
Tablet;
Stringname;
publicChef(Stringname,Tablet){
this.t=t;
this.name=name;
}
publicvoidrun(){
while(true){
Foodf=make();
System.out.println(name+"putaFood:"+f);
putFood(f);
}
}
privateFoodmake(){
Randomr=newRandom(200);
try{
Thread.sleep(200+r.nextInt());
}catch(Exceptione){}
returnnewFood();
}
publicvoidputFood(Foodf){//方法本身不能同步,因为它同步的是this.即Chef的实例
synchronized(t){//要保护的是t
while(t.size()>=t.maxSize){
try{
t.wait();
}
catch(Exceptione){}
}
t.add(f);
t.notifyAll();
}
}
}
2.同步的范围,在本例中是放和取两个方法,不能把做菜和吃菜这种各自不相干的工作
放在受保护的范围中.
3.参与者与容积比.
对于生产者和消费者的比例,以及桌子所能放置最多菜的数量三者之间的关系
是影响性能的重要因素,如果是过多的生产者在等待,则要增加消费者或减少生产者的数据,反之
则增加生产者或减少消费者的数量.
另外如果桌子有足够的容量可以很大程序提升性能,这种情况下可以同时提高生产者和
消费者的数量,但足够大的容时往往你要有足够大的物理内存.
分享到:
相关推荐
Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...
《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...
C#多线程编程实战.pdf
《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...
C#多线程编程实例实战 C#多线程编程实例实战是指在C#语言中实现多线程编程的实例和实战经验。多线程编程是指在同一个进程中创建多个线程,以便提高程序的执行效率和响应速度。在C#语言中,可以使用Thread类和线程池...
《汪文君JAVA多线程编程实战》是一本专注于Java多线程编程的实战教程,由知名讲师汪文君倾力打造。这本书旨在帮助Java开发者深入理解和熟练掌握多线程编程技术,提升软件开发的效率和质量。在Java平台中,多线程是...
《C++多线程编程实战》是一本深入探讨C++并发编程领域的专著,由姜佑译成中文。这本书旨在帮助读者理解并掌握C++中的多线程技术,从而能够利用这种技术创建高效的并行应用程序。C++作为一门强大且灵活的编程语言,其...
《Java多线程编程实战指南(核心篇)》以基本概念、原理与方法为主线,辅以丰富的实战案例和生活化实例,并从Java虚拟机、操作系统和硬件多个层次与角度出发,循序渐进、系统地介绍Java平台下的多线程编程核心技术及...
C++多线程 windows
《C#多线程编程实战(原书第二版)源码》是一本深入探讨C#中多线程技术的专业书籍,其源码提供了丰富的实践示例,帮助读者掌握并发编程的核心概念和技术。在C#中,多线程是实现高性能、响应式应用程序的关键组成部分...
本资源"《C#多线程编程实战》完整源码"提供了丰富的实例,适用于学习和实践C#中的多线程概念。 在C#中,多线程允许应用程序同时执行多个独立的任务,提高系统利用率并优化性能。.NET框架为开发者提供了强大的支持,...
《C#多线程编程实战》.((美)Eugene Agafonov).[PDF]《C#多线程编程实战》.((美)Eugene Agafonov).[PDF]《C#多线程编程实战》.((美)Eugene Agafonov).[PDF]
《C#多线程编程实战》是一本专为C#开发者设计的深度学习多线程技术的书籍。这本书全面覆盖了C#中的并发和多线程编程,旨在帮助读者掌握如何在多核处理器环境下有效利用系统资源,提高程序的执行效率和响应速度。 在...
《多线程编程实战指南-核心篇》是针对Java开发者深入理解并掌握多线程编程的一本实战性书籍。在当今的并发计算环境中,多线程技术是必不可少的知识点,它能够有效地利用多核处理器资源,提高程序的执行效率。本书以...
### 多线程编程实战篇知识点详解 #### 一、多线程编程的基本原则 多线程编程在软件开发中占据着重要的地位,特别是在需要高效利用计算机资源的应用场景下。多线程编程的核心在于如何有效地管理和协调多个线程之间...
P303.zip
本书是一本通俗易懂的C#多线程编程指南,通过70多个容易理解的示例,循序渐进地讲解C#5.0中的异步及并发编程,引导读者了解Windows下C#多线程编程的多样性。 通过阅读本书,你将学到: 使用原始线程、异步线程,...
高清文档,希望对C++学习者有用
《Java多线程编程实战指南(设计模式篇)》由黄文海撰写,是一本深入探讨Java多线程编程和设计模式的专业书籍。书中详细介绍了如何在Java环境中利用多线程来实现高效的并发处理,同时结合设计模式,帮助开发者更好地...
本资源"《C#多线程编程实战源码》"提供了丰富的实例,帮助开发者深入理解和实践C#中的多线程技术。 1. **线程基础**:线程是操作系统分配CPU时间的基本单元,一个进程可以有多个线程,每个线程执行不同的任务。在C#...