专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » java多线程编程:超线程多核心下Java多线程编程技术分析 »正文

java多线程编程:超线程多核心下Java多线程编程技术分析

来源: 发布时间:星期三, 2008年12月17日 浏览:2次 评论:0
阅读提要:在引入Java多线程技术后几乎所有应用开发在性能上都得到了很大改进本文将通过探讨超线程技术以及新出现多核心Intel处理器技术来分析这些线程技术是怎样成为Java编程个标准部分   、Java环境下多线程技术   构建线程化应用往往会对带来重要性能影响例如请考虑这样它从磁盘读取大量数据并且在把它们写到屏幕的前处理这些数据(例如个DVD播放器)个传统单线程(今天所使用大多数客户端)上次只有个任务执行个这些活动分别作为个序列区别阶段发生只有在块已定义大小数据读取完成时才能进行数据处理因此能处理数据逻辑直到磁盘读操作完成后才得到执行这将导致非常差性能问题   在个多线程可以分配个线程来读取数据让另个线程来处理数据而让第 3个线程把数据输送到图形卡上去这 3个线程可以并行运行;这样以来在磁盘读取数据同时仍然可以处理数据从而提高了整体性能许多大量举例都可以被设计来同时做两件事情以进步提高性能Java虚拟机(JVM)本身就是基于此原因广泛使用了多线程技术   本文将讨论创建多线程Java代码以及些进行并行设计最好练习;另外还介绍了对开发者极为有用些工具和资源篇幅所限不可能全面论述这些问题所以我想只是重点提下极重要地方并提供给你相应参考信息    2、线程化Java代码   所有都至少使用个线程在C/C和Java中这是指用对而启动那个线程另外线程创建需要若干步骤:创建个新线程然后指定给它某种工作旦工作做完该线程将自动被JVM所杀死   Java提供两个思路方法来创建线程并且指定给它们工作种思路方法是子类化JavaThread类(在java.lang包中)然后用该线程工作重载run思路方法下面是这种思路方法个举例: public SimpleThread extends Thread {  public SimpleThread(String str) {   super(str);  }  public void run {   for ( i = 0; i < 10; i) {    .out.prln(i + " " + getName);    try {     sleep((long)(Math.random * 1000));    } catch (InterruptedException e) {}   }   .out.prln("DONE! " + getName);  } }   这个类子类化Thread并且提供它自己run思路方法上面代码中运行个循环来打印传送过来串到屏幕上然后等待个随机时间数目在循环十次后打印"DONE!"然后退出-并由它杀死这个线程下面是创建线程: public TwoThreadsDemo {  public void (String args) {    SimpleThread("Do it!").start;    SimpleThread("Definitely not!").start;  } }   注意该代码极为简单:开始给定个名字(它是该线程将要打印输出串)并且start然后startrun思路方法结果如下所示: 0 Do it! 0 Definitely not! 1 Definitely not! 2 Definitely not! 1 Do it! 2 Do it! 3 Do it! 3 Definitely not! 4 Do it! 4 Definitely not! 5 Do it! 5 Definitely not! 6 Do it! 7 Do it! 6 Definitely not! 8 Do it! 7 Definitely not! 8 Definitely not! 9 Do it! DONE! Do it! 9 Definitely not! DONE! Definitely not!   正如你所看到这两个线程输出结果纠合到个单线程所有"Do it!"命令将起打印后面跟着输出"Definitely not!"   这个区别运行将产生区别结果这种不确定性来源于两个方面:在循环中有个随机暂停;更为重要线程执行时间没法保证这是个关键原则JVM将根据它自己时间表运行这些进程(虚拟机般支持尽可能快地运行这些线程但是没法保证何时运行个给定线程)对于每个线程可以使个优先级和的相关联以确保关键线程被JVM处理在次要线程的前   启动个线程第 2种思路方法是使用个实现Runnable接口类-这个接口也定义在java.lang中这个Runnable接口指定个run思路方法-然后该思路方法成为线程类似于前面代码   现在Java般风格是支持继承接口通过使用接口个类在后面仍然能够继承(子类化)-如果必要话(例如如果该类要在后面作为个applet使用就会发生这种情况)   3、线程含义   在采用多线程技术增强性能同时它也增加了内部运行复杂性这种复杂性主要是由线程的间交互引起熟悉这些问题是很重要随着越来越多核心芯片加入到Intel处理器中要使用线程数目也将相应地增长如果在创建多线程时不能很好地理解这些问题那么是调试时将很难发现因此让我们先看下这些问题及其解决办法   等待另个线程完成:假定我们有个整型要进行处理我们可以遍历这个每次个整数并执行相应操作更高效地我们可以建立多个线程这样以来让每个线程处理部分假定我们在开始下步的前必须等待所有线程结束为了暂时同步线程的间活动这些线程使用了join思路方法-它使得个线程等待另个线程完成加入线程(线程B)等待被加入线程(线程A)完成在join个可选超时值使得线程B可以继续处理其它工作-如果线程A在给定时间帧内还没有终止这个问题将触及到线程核心复杂性-等待线程问题下面我们将讨论这个问题   在锁定对象上等待:假定我们编写个航空公司座位分配系统在开发这种大型为每个连接到该软件Software用户分配个线程是很经常个线程对应个机票销售员(在很大系统中情况并非总是如此)如果有两个用户同时想分配同个座位就会出现问题除非采取特殊措施否则个线程将分配该座位而另个线程将会在做相同事情两个用户都会认为他们在这趟航班上拥有个分配位子   为了避免两个线程同时修改数据项我们让个线程在修改数据前锁定数据项用这种思路方法当第 2个线程开始作修改时它将等待到第个线程释放锁为止当这种发生时线程将会看到座位已被分配而对于座位分配请求就会失败两个线程竞争分配座位问题也就是著名竞争条件问题而当竞争发生时有可能导致系统泄漏为此最好办法就是锁定任何代码-该代码存取个可由多个线程共同存取变量   在Java中存在好几种锁选择其中最为常用是使用同步机制个思路方法签名包含同步时在任何给定时间只有个线程能够执行这个思路方法然后当该思路方法完成执行时对该思路方法锁定即被解除例如 protected synchronized reserveSeat ( Seat seat_number ){   ( seat_number.getReserved false ){   seat_number.Reserved;    ( 0 );  }   ( -1 ); }   就是个思路方法-在这种思路方法中每次只运行个线程这种锁机制就打破了上面所描述竞争条件   使用同步是处理线程间交互几种思路方法中J2SE 5.0中添加了若干方便思路方法来锁定对象大多数这些思路方法可以在包java.util.concurrent.locks中找到-旦你熟悉了Java线程就应该对它进行详细研究   在锁机制解决了竞争条件同时它们也带来了新复杂性在这种情况下最困难问题就是死锁假定线程A在等待线程B并且线程B在等待线程A那么这两个线程将永远被锁定-这正是术语死锁意义死锁问题可能很难判定并且必须相当小心以确保在线程的间没有这种依赖性    4、使用线程池   如前所提及在线程完成执行时它们将被JVM杀死而分配给它们内存将被垃圾回收机制所回收不断地创建和毁灭线程所带来麻烦是它浪费了时钟周期创建线程确实耗费额外时间个通用且最好实现是在运行早期就分配组线程(称为个线程池)然后在这些线程可用时再使用它们通过使用这种方案在创建时分配给个线程指定功能就是呆在线程池中并且等待分配项工作然后当分配工作完成时该线程被返回到线程池   J2SE 5.0引入了java.util.concurrent包-它包括了个预先构建线程池框架-这大大便利了上述思路方法实现有关Java线程池更多信息及部教程请参见http://java.sun.com/developer/JDCTechTips/2004/tt1116.html#2   在设计线程和线程池时自然出现有关应该创建多少线程问题答案看你怎样计划使用这些线程如果你基于分离任务来用线程划分工作那么线程数目等于任务数目例如个字处理器可能使用个线程用于显示(在几乎所有系统中线程负责更新用户接口)个用于标记文档第 3个用于拼写检查而第 4个用于其它后台操作在这种情况中创建 4个线程是理想并且它们提供了编写该类软件Software个很自然思路方法   然而如果-象早些时候所讨论那个样-使用多个线程来做类似工作那么线程最佳数目将是系统资源反映特别是处理器上可执行管道数目和处理器数目反映在采用英特尔处理器超线程技术(HT技术)系统上当前在每个处理器核心上有两个执行管道最新多核心处理器在每个芯片上有两个处理器核心英特尔指出将来芯片有可能具有多个核心大部分是额外核心会带来更高性能而不会从根本上增加热量或电量消耗因此管道数将会越来越多   照上面这些体系结构所作算术建议个双核心Pentium 4处理器系统上可以使用 4条执行管道并因此可以使用 4个线程将会提供理想性能个双处理器英特尔Xeon?处理器工作站上理想线程数目是4目前Xeon芯片提供HT技术但是没提供多核心模型你可以参考下面文档来了解这些新型处理器上执行管道数目(http://www.el.com/cd/ids/developer/asmo-na/eng/196716.htm)    5、小结   你当在平台上运行线程化Java你将可能想要监控在处理器上加载过程和线程执行最好获得这些数据和管理JVM怎样处理并行处理JVM的是BEAWebLogic JRockitJRockit还有其它些由来自于BEA和Intel公司工程师专门为Intel平台设计和优化优点   不考虑你使用哪种JVMIntelVTune Performance Analyzer将会给你个有关JVM怎样执行你代码很深入视图-这包括每个线程性能瓶颈等另外Intel还提供了有关如何在Java环境下使用VTune Performance Analyzer白皮书[PDF 2MB]   总的本文提供了线程在Java平台工作机理分析由于Intel还将继续生产HT技术处理器并且发行更多多核心芯片所以想从这些多管道中得到性能效益压力也会增加并且由于核心芯片数目增加管道数目也将相应地增加利用它们优点办法就是使用多线程技术如在本文中所讨论并且Java多线程优势也越来越明显

相关文章

读者评论

  • 共0条 分0页

发表评论

  • 昵称:
  • 内容: