`
zzhaog
  • 浏览: 59400 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Thread and Runnable区别

阅读更多

Thread is the 进程, Runnable is the 进程对象

[第一需要弄清的问题]

  如同程序和进程的区别,要掌握多线程编程,第一要弄清的问题是:线程对象和线程的区别

  线程对象是可以产生线程的对象。比如在java平台中Thread对象,Runnable对象。线程,是指正在执行的一个指点令序列。在java平台上是指从一个线程对象的start()开始,运行run方法体中的那一段相对独立的过程。

  鉴于作者的水平,无法用更确切的词汇来描述它们的定义。但这两个有本质区别的概念请初学者细细体会,随着介绍的深入和例程分析的增加,就会慢慢明白它们所代表的真实含义。

  天下难事必始于易,天下大事必始于细。

  让我们先从最简单的"单线程"来入手:(1)带引号说明只是相对而言的单线程,(2)基于java。

    class BeginClass{

public static void main(String[] args){

for(int i=0;i<100;i++)

System.out.println("Hello,World!");

}

}

  如果我们成功编译了该java文件,然后在命令行上敲入:

  java BeginClass

  现在发生了什么呢?每一个java程序员,从他开始学习java的第一分钟里都会接触到这个问

  题,但是,你知道它到底发生发什么?

JVM进程被启动,在同一个JVM进程中,有且只有一个进程,就是它自己。然后在这个JVM环境中,所有程序的运行都是以线程来运行。JVM最先会产生一个主线程,由它来运行指定程序的入口点。在这个程序中,就是主线程从main方法开始运行。当main方法结束后,主线程运行完成。JVM进程也随之退出。

  我们看到的是一个主线程在运行main方法,这样的只有一个线程执行程序逻辑的流程我们称

  之为单线程。这是JVM提供给我们的单线程环境,事实上,JVM底层还至少有垃圾回收这样的后台线程以及其它非java线程,但这些线程对我们而言不可访问,我们只认为它是单线程的。

  主线程是JVM自己启动的,在这里它不是从线程对象产生的。在这个线程中,它运行了main方法这个指令序列。理解它,但它没有更多可以研究的内容。

  [接触多线程]

    class MyThread extends Thread{

public void run(){

System.out.println("Thread say:Hello,World!");

}

}



public class MoreThreads{

public static void main(String[] args){

new MyThread();

new MyThread().start();

System.out.println("Main say:Hello,World");

}

}

  执行这个程序,main方法第一行产生了一个线程对象,但并没有线程启动。

  main方法第二行产生了一个线程对象,并启动了一个线程。

  main方法第三行,产生并启动一个线程后,主线程自己也继续执行其它语句。

  我们先不研究Thread对象的具体内容,稍微来回想一下上面的两个概念,线程对象线程。在JAVA中,线程对象是JVM产生的一个普通的Object子类。而线程是CPU分配给这个对象的一个运行过程。我们说的这个线程在干什么,不是说一个线程对象在干什么,而是这个运行过程在干什么。如果一时想不明白,不要急,但你要记得它们不是一回事就行了。


现在我们来开始考察JAVA中线程对象。

  在JAVA中,要开始一个线程,有两种方式。一是直接调用Thread实例的start()方法,二是
将Runable实例传给一个Thread实例然后调用它的start()方法。

  在前面已经说过,线程对象和线程是两个完全不同的概念。这里我们再次深入一下,生成一个线程的实例,并不代表启动了线程。而启动线程是说在某个线程对象上启动了该实例对应的线程,当该线程结束后,并不会就立即消失。

  对于从很多书籍上可以看到的基础知识我就不用多说了。既然是基础知识,我也着重于从普通文档上读不到的内容。所以本节我重点要说的是两种线程对象产生线程方式的区别。

class MyThread extends Thread{

public int x = 0;



public void run(){



for(int i=0;i<100;i++){

try{

Thread.sleep(10);

}catch(Exception e){}

System.out.println(x++);



}

}

}

  如果我们生成MyThread的一个实例,然后调用它的start()方法,那么就产生了这个实例对应的线程:

public class Test {

public static void main(String[] args) throws Exception{

MyThread mt = new MyThread();

mt.start();

}

}

  不用说,最终会打印出0到99,现在我们稍微玩一点花样:

public class Test {

public static void main(String[] args) throws Exception{

MyThread mt = new MyThread();

mt.start();

System.out.println(101);

}

}

  也不用说,在基础篇(一)中我们知道由于单CPU的原因,一般会先打印101,然后打印0到99。不过我们可以控制线程让它按我们的意思来运行:

public class Test {

public static void main(String[] args) throws Exception{

MyThread mt = new MyThread();

mt.start();

mt.join();

System.out.println(101);

}

}

  好了,我们终于看到,mt实例对应的线程(假如我有时说mt线程请你不要怪我,不过我尽量不这么说)。在运行完成后,主线程才打印101。因为我们让当前线程(这里是主线程)等待mt线程的运行结束。"在线程对象a上调用join()方法,就是让当前正在执行的线程等待线程对象a对应的线程运行完成后才继续运行。" 请大家一定要深刻理解并熟记这句话,而我这里引出这个知识点的目的是为了让你继续看下面的例子:

public class Test {

public static void main(String[] args) throws Exception{

MyThread mt = new MyThread();

mt.start();

mt.join();

Thread.sleep(3000);

mt.start();

}

}

  当线程对象mt运行完成后,我们让主线程休息一下,然后我们再次在这个线程对象上启动线程。结果我们看到:

  Exception in thread "main" java.lang.IllegalThreadStateException

  也就是这种线程对象一时运行一次完成后,它就再也不能运行第二次了。我们可以看一下它有具体实现:

    public synchronized void start() {

if (started)

throw new IllegalThreadStateException();

started = true;

group.add(this);

start0();

}

  一个Thread的实例一旦调用start()方法,这个实例的started标记就标记为true,事实中不管这个线程后来有没有执行到底,只要调用了一次start()就再也没有机会运行了,这意味着:

[通过Thread实例的start(),一个Thread的实例只能产生一个线程]

  那么如果要在一个实例上产生多个线程(也就是我们常说的线程池),我们应该如何做呢?这就是Runnable接口给我们带来的伟大的功能。

class R implements Runnable{

private int x = 0;

public void run(){



for(int i=0;i<100;i++){

try{

Thread.sleep(10);

}catch(Exception e){}

System.out.println(x++);



}

}

}

  
正如它的名字一样,Runnable的实例是可运行的,但它自己并不能直接运行,它需要被Thread对象来包装才行运行:

public class Test {

public static void main(String[] args) throws Exception{

new Thread(new R()).start();

}

}

  当然这个结果和mt.start()没有什么区别。但如果我们把一个Runnable实例给Thread对象多次包装,我们就可以看到它们实际是在同一实例上启动线程:

public class Test {

public static void main(String[] args) throws Exception{

R r = new R();

for(int i=0;i<10;i++)

new Thread(r).start();

}

}

  x是实例对象,但结果是x被加到了999,说明这10个线程是在同一个r对象上运行的。请大家注意,因为这个例子是在单CPU上运行的,所以没有对多个线程同时操作共同的对象进行同步。这里是为了说明的方便而简化了同步,而真正的环境中你无法预知程序会在什么环境下运行,所以一定要考虑同步。

  到这里我们做一个完整的例子来说明线程产生的方式不同而生成的线程的区别:

package debug;



import java.io.*;

import java.lang.Thread;





class MyThread extends Thread{

public int x = 0;



public void run(){

System.out.println(++x);

}

}



class R implements Runnable{

private int x = 0;

public void run(){

System.out.println(++x);

}

}



public class Test {

public static void main(String[] args) throws Exception{



for(int i=0;i<10;i++){

Thread t = new MyThread();

t.start();

}

Thread.sleep(10000);//让上面的线程运行完成

R r = new R();

for(int i=0;i<10;i++){

Thread t = new Thread(r);

t.start();

}

}

}

  上面10个线程对象产生的10个线程运行时打印了10次1。下面10个线程对象产生的10个线程运行时打印了1到10。我们把下面的10个线程称为同一实例(Runnable实例)的多个线程

 

转载自:http://www.blogjava.net/sunxiaobo/archive/2008/02/28/182788.html

分享到:
评论

相关推荐

    Android开发笔记之:Handler Runnable与Thread的区别详解

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能...

    Thread、Handler和HandlerThread关系详解

    前几天看到一道面试题:Thread、Handler和HandlerThread有什么区别?,这个题目有点意思,对于很多人来说,可能对Thread和Handler很熟悉,主要涉及到Android的消息机制(Handler、Message、Looper、MessageQueue),...

    2D弹性球动画(对初学者很有参考价值)

    The thread itself is created and started in * the start() method. */ public void run() { while (!pleaseStop) { // Loop until we're asked to stop animate(); // Update and request redraw ...

    java并发源码-Concurrency-in-Java-Runnable-and-Thread-Source-code:演示Java并发

    java 并发源码

    ym_java-YOYOPlayer-src

    public class BasicPlayer implements BasicController, Runnable { public static int EXTERNAL_BUFFER_SIZE = 4000 * 4; public static int SKIP_INACCURACY_SIZE = 512; protected Thread m_thread = null; ...

    Thread-Programming-and-Non-blocking-Java-Servers

    线程编程和非阻塞Java服务器 #####何时以及为什么我们将在程序中使用线程? 一个用例是,当您进行长时间运行的操作时,仍然想保持主线程空闲以进行UI ... new Thread ( new (class implements Runnable / Callable )) .

    后端JAVA虚拟机JVM调优必备工具

    IBM Thread and Monitor Dump Analyzer for Java专业JVM调优工具 一、使用方法 1.使用java -jar启动程序 2.找到需要分析的jvm进程 3.使用jstack [pid] &gt; /tmp/sdapjvmlog.txt导出进程的详细日志 4.使用程序打开...

    基于JAVA的网络聊天室(BS)

    * and open the template in the editor. */ package client; /** * * @author Administrator */ import java.awt.*; import java.io.*; import java.net.*; import java.applet.*; import java.util....

    Android代码-teaspoon

    It makes more clear and easy to execute your method on ui thread or background thread. Usage You've seen this code at least once. void someUiLogicInActivity() { this.runOnUiThread(new Runnable() { @...

    Android定时器实现定时执行、重复执行、定时重复执行、定次数执行的多种方式

    1、 Thread(new Runnable) 2、Thread() 3、Timer 4、Handler ····· 代码如下: 1、布局 &lt;?xml version=1.0 encoding=utf-8?&gt; &lt;LinearLayout xmlns:android=...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4 │ 高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4 │ 高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4 │ 高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4 │ 高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机...

    android AsynTask处理返回数据和AsynTask使用get,post请求

    开启新的线程可以new Thread() 或实现Runnable接口 什么要使用AsyncTask呢? 如果是使用Thread的run()方法,run()结束之后没有返回值。所以必须要自己建立通信机制 AsyncTask将所有的线程通信都封装成回调函数,...

    testActiveMQ.rar

    * See the License for the specific language governing permissions and * limitations under the License. */ // START SNIPPET: demo /*extern "C" {*/ #include #include &lt;decaf/lang/Thread.h&gt; #include ...

    redar:Java Swift Knife 项目.. - 线程、Quartz、Spring、Spring Integration、Apache Mina、Python

    多线程示例####1.1 ThreadLocals + ThreadPools 该模块通过确保在 Runnable 执行结束时删除 ThreadLocal 上下文来测试内存泄漏保护####1.2。 分叉和加入本模块用于测试 Fork And Join ####1.3。 通过 RMI 使用信号...

    Java测试题2答案

    下列说法正确的是 BC A java.lang.Clonable是类 B java.lang.Runnable是接口 C Double对象在java.lang包中 D Double a=1.0是正确的java语句 9.指出正确的表达式AB &lt;br&gt;B Double a=new Double(1.0)...

    幻灯片java手动播放

    public class SR_Slider extends Frame implements ActionListener, WindowListener, Runnable { public static void main(String Pagli[]) { new SR_Slider(); } Thread time; //new thread File fl; URL ...

    android.os.NetworkOnMainThreadException

    文章目录android.os.NetworkOnMainThreadException问题分析查阅资料解决方案知识要点: RunOnUiThread 和 new Thread(new Runnable()).start() 的区别先说一下 RunonUiThread这时候就需要使用 handler来处理消息 ...

    超级有影响力霸气的Java面试题大全文档

    sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程...

    【面试】可以在子线程直接new一个Handler吗?怎么做?

    可以在子线程直接new一个Handler,不过需要在子线程里先调用Looper.prepare(),new一个... new Thread(new Runnable() { @Override public void run() { Looper.prepare(); new Handler(){ @Override public void

Global site tag (gtag.js) - Google Analytics