Java中Thread和Runnable的区别_第1页
Java中Thread和Runnable的区别_第2页
Java中Thread和Runnable的区别_第3页
Java中Thread和Runnable的区别_第4页
Java中Thread和Runnable的区别_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Thread and RunnableThread is the 进程, Runnable is the 进程对象第一需要弄清的问题如同程序和进程的区别,要掌握多线程编程,第一要弄清的问题是:线程对象和线程的区别。线程对象是可以产生线程的对象。比如在java平台中Thread对象,Runnable对象。线程,是指正在执行的一个指令序列。在java平台上是指从一个线程对象的start()开始,运行run方法体中的那一段相对独立的过程。鉴于作者的水平,无法用更确切的词汇来描述它们的定义。但这两个有本质区别的概念请初学者细细体会,随着介绍的深入和例程分析的增加,就会慢慢明白它们所代表的真实含义。天下

2、难事必始于易,天下大事必始于细。让我们先从最简单的单线程来入手:(1)带引号说明只是相对而言的单线程,(2)基于java。 class BeginClasspublic static void main(String args)for(int i=0;i100;i+)System.out.println(Hello,World!);如果我们成功编译了该java文件,然后在命令行上敲入:javaBeginClass现在发生了什么呢?每一个java程序员,从他开始学习java的第一分钟里都会接触到这个问题,但是,你知道它到底发生发什么?JVM进程被启动,在同一个JVM进程中,有且只有一个进程,就是

3、它自己。然后在这个JVM环境中,所有程序的运行都是以线程来运行。JVM最先会产生 一个主线程,由它来运行指定程序的入口点。在这个程序中,就是主线程从main方法开始运行。当main方法结束后,主线程运行完成。JVM进程也随之退出。我们看到的是一个主线程在运行main方法,这样的只有一个线程执行程序逻辑的流程我们称之为单线程。这是JVM提供给我们的单线程环境,事实上,JVM底层还至少有垃圾回收这样的后台线程以及其它非java线程,但这些线程对我们而言不可访问,我们只认为它是单线程的。主线程是JVM自己启动的,在这里它不是从线程对象产生的。在这个线程中,它运行了main方法这个指令序列。理解它,但

4、它没有更多可以研究的内容。接触多线程 class MyThread extends Threadpublic void run()System.out.println(Thread say:Hello,World!);public class MoreThreadspublic static void main(String args)new MyThread();new MyThread().start();System.out.println(Main say:Hello,World);执行这个程序,main方法第一行产生了一个线程对象,但并没有线程启动。main方法第二行产生了一个线程对

5、象,并启动了一个线程。main方法第三行,产生并启动一个线程后,主线程自己也继续执行其它语句。我们先不研究Thread对象的具体内容,稍微来回想一下上面的两个概念,线程对象和线程。在JAVA中,线程对象是JVM产生的一个普通的Object子类。而线程是CPU分配给这个对象的一个运行过程。我们说的这个线程在干什么,不是说一个线程对象在干什么,而是这个运行过程在干什么。如果一时想不明白,不要急,但你要记得它们不是一回事就行了。现在我们来开始考察JAVA中线程对象:在JAVA中,要开始一个线程,有两种方式。一是直接调用Thread实例的start()方法,二是将Runable实例传给一个Thread

6、实例然后调用它的start()方法。在前面已经说过,线程对象和线程是两个完全不同的概念。这里我们再次深入一下,生成一个线程的实例,并不代表启动了线程。而启动线程是说在某个线程对象上启动了该实例对应的线程,当该线程结束后,并不会就立即消失。对于从很多书籍上可以看到的基础知识我就不用多说了。既然是基础知识,我也着重于从普通文档上读不到的内容。所以本节我重点要说的是两种线程对象产生线程方式的区别。class MyThread extends Threadpublic int x = 0;public void run()for(int i=0;i100;i+)tryThread.sleep(10);

7、catch(Exception e)System.out.println(x+);如果我们生成MyThread的一个实例,然后调用它的start()方法,那么就产生了这个实例对应的线程:public class Test public static void main(String args) throws ExceptionMyThread mt = new MyThread();mt.start();不用说,最终会打印出0到99,现在我们稍微玩一点花样:public class Test public static void main(String args) throws Excepti

8、onMyThread mt = new MyThread();mt.start();System.out.println(101);也不用说,在基础篇(一)中我们知道由于单CPU的原因,一般会先打印101,然后打印0到99。不过我们可以控制线程让它按我们的意思来运行:public class Test public static void main(String args) throws ExceptionMyThread mt = new MyThread();mt.start();mt.join();System.out.println(101);好了,我们终于看到,mt实例对应的线程(假

9、如我有时说mt线程请你不要怪我,不过我尽量不这么说)。在运行完成后,主线程才打印101。因为 我们让当前线程(这里是主线程)等待mt线程的运行结束。在线程对象a上调用join()方法,就是让当前正在执行的线程等待线程对象a对应的线程运行 完成后才继续运行。请大家一定要深刻理解并熟记这句话,而我这里引出这个知识点的目的是为了让你继续看下面的例子:public class Test public static void main(String args) throws ExceptionMyThread mt = new MyThread();mt.start();mt.join();Thread

10、.sleep(3000);mt.start();当线程对象mt运行完成后,我们让主线程休息一下,然后我们再次在这个线程对象上启动线程。结果我们看到:Exceptioninthreadmainjava.lang.IllegalThreadStateException也就是这种线程对象一时运行一次完成后,它就再也不能运行第二次了。我们可以看一下它有具体实现: public synchronized void start() if (started)throw new IllegalThreadStateException();started = true;group.add(this);start

11、0();一个Thread的实例一旦调用start()方法,这个实例的started标记就标记为true,事实中不管这个线程后来有没有执行到底,只要调用了一次start()就再也没有机会运行了,这意味着:通过Thread实例的start(),一个Thread的实例只能产生一个线程那么如果要在一个实例上产生多个线程(也就是我们常说的线程池),我们应该如何做呢?这就是Runnable接口给我们带来的伟大的功能。class R implements Runnableprivate int x = 0;public void run()for(int i=0;i100;i+)tryThread.slee

12、p(10);catch(Exception e)System.out.println(x+);正如它的名字一样,Runnable的实例是可运行的,但它自己并不能直接运行,它需要被Thread对象来包装才行运行:public class Test public static void main(String args) throws Exceptionnew Thread(new R().start();当然这个结果和mt.start()没有什么区别。但如果我们把一个Runnable实例给Thread对象多次包装,我们就可以看到它们实际是在同一实例上启动线程:public class Test

13、public static void main(String args) throws ExceptionR r = new R(); /Runnable对象只是创建了一次,但是通过for循环用Thread包装后生成了十个Thread线程对象,并启动了10次,但是10次都是针对这同一个Runnable对象的,执行的也是Runnable的同一个run函数,同一段代码。for(int i=0;i10;i+)new Thread(r).start();x是实例对象,但结果是x被加到了999,说明这10个线程是在同一个r对象上运行的。请大家注意,因为这个例子是在单CPU上运行的,所以没有对多个线程同时

14、操作共同的对象进行同步。这里是为了说明的方便而简化了同步,而真正的环境中你无法预知程序会在什么环境下运行,所以一定要考虑同步。到这里我们做一个完整的例子来说明线程产生的方式不同而生成的线程的区别:package debug;import java.io.*;import java.lang.Thread;class MyThread extends Threadpublic int x = 0;public void run()System.out.println(+x);class R implements Runnableprivate int x = 0;public void run(

15、)System.out.println(+x);public class Test public static void main(String args) throws Exceptionfor(int i=0;i10;i+)Thread t = new MyThread();t.start();Thread.sleep(10000);/让上面的线程运行完成R r = new R();for(int i=0;i10;i+)Thread t = new Thread(r);t.start();上面10个线程对象产生的10个线程运行时打印了10次1。下面10个线程对象产生的10个线程运行时打印了

16、1到10。我们把下面的10个线程称为同一实例(Runnable实例)的多个线程。package a.b;class MyThread extends Thread public int x = 0;/为了验证每次新建一个Thread对象时,是否会执行run方法之外的初始化代码,这里加了一个非静态代码块,因为若非静态代码块执行了,那么public int x = 0也会被执行。public int count = 1;System.out.println(in MyThread non-static block: x= + count+);public void run() System.out

17、.println(in MyThread run: x=+ +x);class R implements Runnable /为了验证每次新建一个Thread对象时,是否会执行run方法之外的初始化代码,这里加了一个非静态代码块,因为若非静态代码块执行了,那么public int x = 0也会被执行。private int x = 0;System.out.println(in Runnable non-static block: x= + x);public void run() System.out.println(in Runnable run : x= + +x);public cl

18、ass ThreadTest public static void main(String args) throws Exception int x = 1;/R r = new R();for (int i = 0; i 10; i+) /Thread t = new Thread(r);Thread t = new MyThread();t.start();下面为上面的MyThread线程对象启动start对应的结果,可见每次for循环都会创建一个MyThread对象及对应的线程,这时每个线程只是操作自己的MyThread中的数据成员,互不干扰。每次新建一个MyThread对象 ,都会执行run方法前面的初始化操作及非静态代码块,然后再执行run方法。如果上面的ThreadTest改为下面的形式,就是for中是用Runnable对象作为参数得到的Thread对象。public class ThreadTest public static void main(String args) throws Exception int x = 1;R r = new R(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论