现在的位置: 首页 > 综合 > 正文

java的多线程(一)

2013年12月17日 ⁄ 综合 ⁄ 共 3028字 ⁄ 字号 评论关闭

 

一 什么是线程

1 带有自己的程序代码和数据的虚拟处理机的封装。 java.lang.Thread类允许用户创建并控制他们的线程

 

2 线程的三个部分 

 处理机 (CPU)

 代码(Code) 

 数据 (Data)

 

二 怎么使用

两种方法:一种实现Runnable接口,一种集成Thread类

 

1 实现接口示例:

一个Thread类构造函数带有一个参数,它是 Runnable的一个实例。一个Runnable是由一个实现了Runnable接口(即,提供了一个public void run()方法)的类产生的。 

 

代码示例:

 

    1.public class ThreadTest {  

    2.public static void main(String args[]) {  

    3.Xyz r = new Xyz();  

    4.Thread t = new Thread(r);  

    5.}  

    6.}  

    7. 

    8.class Xyz implements Runnable {  

    9.int i;  

   10. 

   11.public void run() {  

   12.while (true) {  

   13.System.out.println("Hello " + i++);  

   14.if (i == 50) break;  

   15.}  

   16.}  

   17.}  

 

 

代码说明:

 

首先,main()方法构造了 Xyz 类的一个实例 r。实例 r 有它自己的数据,在这里就是整数 i。因为实例 r 是传给 Thread的类构造函数的,所以 r 的整数 i 就是线程运行时刻所操作的数据。线程总是从它所装载的Runnable实例(在本例中,这个实例就是r。)的 run()方法开

始运行。 一个多线程编程环境允许创建基于同一个 Runnable 实例的多个线程。这可以通过以下方法来做到:  

Thread t1= new Thread(r); 

Thread t2= new Thread(r); 

如果t1,t2都调用start()方法的话就是实现了多线程,此时,这两个线程共享数据和代码。 

 

 

注:Java 中引入线程机制的目的在于实现多线程,以提高程序的效能。这主要是通过多线程之间共享代码和数据来实现的,例如可以使用同一个 Runnable 接口(的实现类)类型的实例构造多个线程。 

 

 

2 继承Thread

 

 

 

三 为什么要使用

 

与用户的更好交互(Better Interaction with the User) 
如果只有一个线程,那一个程序在同一时刻只能做一件事情。以字处理程序为例,当第一个文档正在格式化和排队打印时,可以打开第二个文档那该多好啊。在一些早前的字处理软件中,当用户想要打印一个文档时,如果该文档正在准备并发送给打印机时,他只好等待。(即,用户不能在等待打印同时,用该软件做其他事情)现代字处理软件开发利用了多线程可以同时做两件事情。在单处理器(one-processor)的系统中,可通过操作系统在两个任务之间快速的来回切换来模拟此场景,以此来实现更好的与用户交互。 

从微处理器的角度来看,即使是最快的打字员在按键之间也花费了巨大的时间。在这些大量的时间间隙,处理器可以处理其他任务。当另外一个线程停止了其他工作时,如果一个线程总在等待给用户的动作一个快速的响应,比如点击鼠标或按键,用户将会从系统中感觉到更好的响应。 

模拟同时进行的活动(Simulation of Simultaneous Activities)
 
即使只有一个处理器,Java中的线程好像也是并发运行。处理器运行每个线程一小段时间,并在线程之间切换来模拟并发执行。这使得每个线程看似都独立拥有自己的处理器。利用这一特性,你可以使得多个任务好像正在同时发生。实际上是在上下文(Context)切换到另外线程之前,每个线程只运行很短时间。 

开发利用多处理器(Exploitation of Multiple Processors) 
一些机器中有多个处理器。如果当前的操作系统和JVM的实现开发利用了多处理器,多线程的Java程序能实现真正的线程并发执行。而Java程序不需要修改,因为它已经用了线程。就像这些线程同时运行在不同的处理器上一样,它只能运行得更快。 

当等待慢的I/O操作时,可以做其他事情(Do Other Things While Waiting for Slow IO Operations)
 
相对于处理器中的代码执行速度,对磁盘的输入输出操作,特别是跨网络的操作,速度相对来说是慢的。结果为了等待完成,读写操作可能被阻塞(block)相当长时间。 

在java.io包中,类InputStream有一个read()方法会被阻塞,直到从流(stream)中读一个字节或者抛出一个IOException异常。当等待流上字节的到来时,执行该方法的线程不能做其他事情。如果创建了多线程,当某线程被阻塞后,其他线程就可以完成其他活动。 

例如,你有一个包含多个TextField组件的Java Applet程序,下图显示了两个线程是如何给用户提供更好的用户交互的伪代码。第一个线程是GUI事件线程,该线程大部分时间都在waiForNextEvent()方法中被阻塞。第二个线程是工作线程,它初始化为阻塞状态,在waitUntilSignalled()方法中等待一个继续工作的信号。当所有的TextField组件生成之后,用户点击了传输数据按钮。GUI事件线程被解除阻塞,进入deliverEventToListenser()方法,随又调用actionPerformed()方法,该方法给工作线程一个信号,然后立即返回到waitForNextEvent()方法。工作线程被解除阻塞,离开了waitUntilSignaled()方法,进入gatherDataAndTransmit()方法。工作线程收集用户输入的数据,进行传输,当等待服务器确认信息时又被阻塞。当读取确认信息之后,工作线程返回waitUntilSignalled()方法。 

简化对象建模(Simplify Object Modeling)
 
在构建一个系统,需要对系统按照面向对象进行分析,这可能要求某些对象以线程方式运行。这类对象可被认为是主动的(active),与消极(passive)相对应。一个消极对象只有当该对象的方法被调用是才能修改其内部状态。一个积极对象可以自动改变内部的状态。 
例如,构建一个数字时钟的图形化的组件,该组件显示当前系统那个的小时和分钟。每个60秒,组件中的分钟将会改变。最简单的设计是在时钟组件内创建一个线程,当需要时专门负责修改数字。否则,除了完成而外的任务,还需要一个额外的线程持续地监测是否需要更新数字。如果这个额外的线程需要从InputStream读取数据,然后被阻塞,等待一个字节的时间超过一分钟,那又该怎如何呢?在这里,发挥多线程编程的优势可以简化问题的解决

 

 

 

 

附1:

线程和进程的区别是: 

每个进程都有独立的代码和数据空间(进程上下文),进程切换的开销大。 

线程作为轻量的进程, 同一类线程可以共享代码和数据空间,但每个线程有独立的运行栈和程序计数器,因此线程切换的开销较小。 

多进程——在操作系统中能同时运行多个任务(程序) ,也称多任务。 

多线程——在同一应用程序中有多个顺序流同时执行。 

 

附2:

使用到的方法

1 实现Runnable接口必须重写run()方法

2 使线程运行的话调用start方法


 

 

 

 

 

 

 

 

抱歉!评论已关闭.