博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

java 线程 start() run()

Posted on 2012-06-11 15:24  bw_0927  阅读(369)  评论(0)    收藏  举报

http://hi.baidu.com/shirdrn/blog/item/7b0a8ed7dfbf11daa144dfb2.html

在Java语言中,创建一个线程类,可以继承Thread类。另外,因为Thread实现了Runnable接口,同时实现了Runnable接口中定义的run方法。可以了解一下:

Runnable接口的定义:

package java.lang;
public interface Runnable {

    public abstract void run();
}

Thread类实现了Runnable接口中定义的run方法:

    public void run() {
if (target != null) {
     target.run();
}
    }

其中,target是Thread类中定义的一个私有成员:

    private Runnable target;

你可以在Thread类中看到,target默认情况下为null的:

public Thread(String name) {
init(null, null, name, 0);
    }

init方法声明如下:

private void init(ThreadGroup g, Runnable target, String name,long stackSize);

所以,默认情况下,如果我们自己实现一个线程类继承自Thread类,即使你自己不重写run方法也是可以的,相当于调用Thread类的run方法执行了一个空操作。

注意,run方法是由系统负责调用的,如果我们去进行调用,那么Java中线程方法体的执行和类的成员方法没什么区别了。

例如:

package org.shirdrn.thread.course1;

public class MyThread extends Thread {

public static void main(String[] args) {
   Thread mt = new MyThread();
   mt.start();
}
}

正常运行。

实例化一个线程类,然后必须调用start方法才能使该线程的实例执行run方法。

下面我们重写基类Thread定义的run方法:

package org.shirdrn.thread.course1;

import java.util.Date;

public class MyThread extends Thread {

public void run() {
   Date date = new Date();
   System.out.println(date.toLocaleString());
}

public static void main(String[] args) {
   Thread mt = new MyThread();
   mt.start();
}
}

运行后输出:

2008-12-31 20:30:41

可以看到,启动线程的时候,线程类的实例确实执行了run方法中代码行。因为,在run方法中也是顺序执行每一行代码,所以输出了一个时间。

当然,可以在run方法中调用线程类的成员方法,实现复杂的操作,如下所示:

package org.shirdrn.thread.course1;

import java.util.Date;

public class MyThread extends Thread {

public void run() {
   print();
}

public void print() {
   Date date = new Date();
   System.out.println(date.toLocaleString());
}

public static void main(String[] args) {
   Thread mt = new MyThread();
   mt.start();
}
}

调用成员方法print,与上面实现的功能是一样的,输出一个当前时间。

下面实现一个,每经过2秒钟打印出当前时间,其实比较简单,只要在run方法中用一个循环就可以,如下所示:

package org.shirdrn.thread.course1;

import java.util.Date;

public class MyThread extends Thread {

public void run() {
   while(true) {
    print();
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
}

public void print() {
   Date date = new Date();
   System.out.println(date.toLocaleString());
}

public static void main(String[] args) {
   Thread mt = new MyThread();
   mt.start();
}
}

可以在控制台上看到,程序一直在运行,每隔2秒钟打印一次当前时间:

2008-12-31 20:37:08
2008-12-31 20:37:10
2008-12-31 20:37:12
2008-12-31 20:37:14
2008-12-31 20:37:16
2008-12-31 20:37:18
2008-12-31 20:37:20
2008-12-31 20:37:22
2008-12-31 20:37:24
2008-12-31 20:37:26
2008-12-31 20:37:28

当然也,我们也可以实现Runnable接口,来实现自己的线程类,如下所示:

package org.shirdrn.thread.course1;

import java.util.Date;

public class MyThreadAoo implements Runnable {

@Override
public void run() {
   while(true) {
    print();
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
}

public void print() {
   Date date = new Date();
   System.out.println(date.toLocaleString());
}

public static void main(String[] args) {
   Thread mt = new Thread(new MyThreadAoo());
   mt.start();
}

}

同上面的运行是一样的,不同的地方,可以看到,在创建一个线程对象的时候,不同于继承Thread类,而是将我们实现的线程类的实例作为Thread的一个参数来构造,然后启动之。

可以看到Thread类的构造方法(一种有8种构造方式):

    public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
    }

另外,还有7种构造方式:

    public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
    }

    public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
    }

    public Thread(String name) {
init(null, null, name, 0);
    }

    public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
    }

    public Thread(Runnable target, String name) {
init(null, target, name, 0);
    }

    public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
    }

    public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
init(group, target, name, stackSize);
    }

举个例子:

package org.shirdrn.thread.course1;

import java.util.Date;

public class ThreadBoo extends Thread {

public ThreadBoo() {
   super();
}

public ThreadBoo(String name) {
   super(name);
}

public void run() {
   while(true) {
    print();
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName());
   }
}

public void print() {
   Date date = new Date();
   System.out.println(date.toLocaleString());
}

public static void main(String[] args) {
   Thread mt = new ThreadBoo();
   mt.start();
   //Thread mtt = new ThreadBoo("I-am-100");
   //mtt.start();

}

}

使用Thread.currentThread().getName()获取当前正在运行的线程的名称。

当使用默认的线程名时,我们可以看到:

2008-12-31 20:54:34
Thread-0
2008-12-31 20:54:36
Thread-0
2008-12-31 20:54:38
Thread-0
2008-12-31 20:54:40

系统会自动生成线程名Thread-0。

将上面的注释打开,将使用默认线程名的代码注释掉,就会看到我们自己为线程命名,如下所示:

2008-12-31 20:58:52
I-am-100
2008-12-31 20:58:54
I-am-100
2008-12-31 20:58:56
I-am-100
2008-12-31 20:58:58

这里,还没有涉及到共享变量,还是非常基础的,对线程有一个最基本的认识吧。