黑马程序员技术交流社区

标题: 【转载】超线程多核心Java多线程编程分析 (1) [打印本页]

作者: 黄玉昆    时间: 2013-4-20 07:56
标题: 【转载】超线程多核心Java多线程编程分析 (1)
读提要:在引入Java多线程技术后,几乎所有应用程序的开发在性能上都得到了很大的改进。本文将通过探讨超线程技术以及新出现的多核心Intel处理器技术来分析这些线程技术是怎样成为Java编程的一个标准部分的。
 一、Java环境下的多线程技术
  构建线程化的应用程序往往会对程序带来重要的性能影响。例如,请考虑这样一个程序,它从磁盘读取大量数据并且在把它们写到屏幕之前处理这些数据(例如一个DVD播放器)。在一个传统的单线程程序(今天所使用的大多数客户端程序)上,一次只有一个任务执行,每一个这些活动分别作为一个序列的不同阶段发生。只有在一块已定义大小的数据读取完成时才能进行数据处理。因此,能处理数据的程序逻辑直到磁盘读操作完成后才得到执行。这将导致非常差的性能问题。
  在一个多线程程序中,可以分配一个线程来读取数据,让另一个线程来处理数据,而让第三个线程把数据输送到图形卡上去。这三个线程可以并行运行;这样以来,在磁盘读取数据的同时仍然可以处理数据,从而提高了整体程序的性能。许多大量的示例程序都可以被设计来同时做两件事情以进一步提高性能。Java虚拟机(JVM)本身就是基于此原因广泛使用了多线程技术。
  本文将讨论创建多线程Java代码以及一些进行并行程序设计的最好练习;另外还介绍了对开发者极为有用的一些工具和资源。篇幅所限,不可能全面论述这些问题,所以我想只是重点提一下极重要的地方并提供给你相应的参考信息。
 二、线程化Java代码
  所有的程序都至少使用一个线程。在C/C++Java中,这是指用对main()的调用而启动的那个线程。另外线程的创建需要若干步骤:创建一个新线程,然后指定给它某种工作。一旦工作做完,该线程将自动被JVM所杀死。
  Java提供两个方法来创建线程并且指定给它们工作。第一种方法是子类化JavaThread(java.lang包中),然后用该线程的工作函数重载run()方法。下面是这种方法的一个示例:
  1. public class SimpleThread extends Thread {
  2.  public SimpleThread(String str) {
  3.   super(str);
  4.  }
  5.  public void run() {
  6.   for (int i = 0; i < 10; i++) {
  7.    System.out.println(i + " " + getName());
  8.    try {
  9.     sleep((long)(Math.random() * 1000));
  10.    } catch (InterruptedException e) {}
  11.   }
  12.   System.out.println("DONE! " + getName());
  13.  }
  14. }
复制代码
  这个类子类化Thread并且提供它自己的run()方法。上面代码中的函数运行一个循环来打印传送过来的字符串到屏幕上,然后等待一个随机的时间数目。在循环十次后,该函数打印"DONE!",然后退出-并由它杀死这个线程。下面是创建线程的主函数:
  1. public class TwoThreadsDemo {
  2.  public static void main (String[] args) {
  3.   new SimpleThread("Do it!").start();
  4.   new SimpleThread("Definitely not!").start();
  5.  }
  6. }
复制代码
  注意该代码极为简单:函数开始,给定一个名字(它是该线程将要打印输出的字符串)并且调用start()。然后,start()将调用run()方法。程序的结果如下所示:
  1. 0 Do it!
  2. 0 Definitely not!
  3. 1 Definitely not!
  4. 2 Definitely not!
  5. 1 Do it!
  6. 2 Do it!
  7. 3 Do it!
  8. 3 Definitely not!
  9. 4 Do it!
  10. 4 Definitely not!
  11. 5 Do it!
  12. 5 Definitely not!
  13. 6 Do it!
  14. 7 Do it!
  15. 6 Definitely not!
  16. 8 Do it!
  17. 7 Definitely not!
  18. 8 Definitely not!
  19. Array Do it!
  20. DONE! Do it!
  21. Array Definitely not!
  22. DONE! Definitely not!
复制代码
  


作者: 黄玉昆    时间: 2013-4-20 07:56
正如你所看到的,这两个线程的输出结果纠合到一起。在一个单线程程序中,所有的"Do it!"命令将一起打印,后面跟着输出"Definitely not!"。
  这个程序的不同运行将产生不同的结果。这种不确定性来源于两个方面:在循环中有一个随机的暂停;更为重要的是,因为线程执行时间没法保证。这是一个关键的原则。JVM将根据它自己的时间表运行这些进程(虚拟机一般支持尽可能快地运行这些线程,但是没法保证何时运行一个给定线程)。对于每个线程可以使一个优先级与之相关联以确保关键线程被JVM处理在次要的线程之前。
  启动一个线程的第二种方法是使用一个实现Runnable接口的类-这个接口也定义在java.lang中。这个Runnable接口指定一个run()方法-然后该方法成为线程的主函数,类似于前面的代码。
  现在,Java程序的一般风格是支持继承的接口。通过使用接口,一个类在后面仍然能够继承(子类化)-如果必要的话(例如,如果该类要在后面作为一个applet使用的话,就会发生这种情况)。

作者: 丘凤光    时间: 2013-4-20 08:27
又复习了一遍多线程的知识
作者: JavaUtil    时间: 2013-4-20 09:06
刚开始看帖子的时候还以为是介绍线程在多核处理器中的处理原理呢。
不过复习了一下线程也是好的。
期待第2部分的转载。谢谢版主!
作者: 罗家辉    时间: 2013-4-20 09:52
单线程相当于一个人做工,多线程相当于多个人做工,谁舒服点,谁效率高点,不言而喻




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2