(See http://www.suneca.com/article.asp?id=53)
进程(Process),简单地讲,就是在操作系统中运行着的任务。比如,我们打开一个word,那我们就是操作系统当中运着着一个进程,打开一个excel,那在操作系统当中就运行着一个进程。而线程(Thread)是在同一应用程序中有多个顺序流(同时)执行,它是进程的实体,一个进程可以拥有多个线程,线程必须有一个父进程。一般情况下,线程具有就绪、阴塞、运行三个基础状态。对于单核CPU的系统上,在某一个时间刻,后台只有一条线程在执行着。
一、线程的实现可以有两种方式,第一种是继承Thread,第二种是实现Runnable接口1、继承Thread
/**
* 使用继承方式的线程实现.
*
* @author <a href="http://www.suneca.com">zizz</a>
*
* @Create-Time:2008 下午10:25:33
*/
public class MyThread extends Thread {
public MyThread ( ) {
}
public void run ( ) {
System .out .println ( "线程运行。。" ) ;
}
public static void main (String [ ] args ) {
//创建一个线程实例
MyThread thread = new MyThread ( ) ;
//线程进入运行态
thread .start ( ) ;
}
}
线程的启动不是程序直接去调用run()方法,而是调用start(),因为线程在什么时候运行,完全是由线程调度器进行决定!
2、实现Runnable接口
/**
* 使用实现Runnable接口的线程.
*
* @author <a href='http://www.suneca.com'>ZIZZ</a>
*
* @Create-Time:2008 下午10:48:31
*/
public class MyRunnable implements Runnable {
public void run ( ) {
System .out .println ( "线程运行。。。" ) ;
}
public static void main (String [ ] args ) {
//构造一个Runnable的实例
MyRunnable runnable = new MyRunnable ( ) ;
//创建新的线程
Thread thread = new Thread (runnable , "T1" ) ;
//线程启动.
thread .start ( ) ;
}
}
Runnable实例的启动不是直接调用run()方法,它需要由一个Thread作为它的载体!
二,多线程
线程的执行是由进程调度器进行调度的,线程在运行时,线程调度器会让线程由运行态转化为阻塞状态,对于线程它是如何运行,线程之间如何去抢夺CPU资源,我们无法控制,以下的例子创建了两条线程,并且这两条线程同时起动。
/**
* 使用继承方式的线程实现.
*
* @author <a href="http://www.suneca.com">zizz</a>
*
* @Create-Time:2008 下午10:25:33
*/
public class MyThread extends Thread {
public MyThread ( ) {
}
public MyThread (String name ) {
super (name ) ;
}
public void run ( ) {
//循环输出1 到 100
for ( int i =1 ;i < =100 ;i + + ) {
System .out .println ( this .getName ( ) + " : " + i ) ;
}
}
public static void main (String [ ] args ) {
//创建一个线程实例
MyThread t1 = new MyThread ( "T1" ) ;
MyThread t2 = new MyThread ( "T2" ) ;
//线程进入运行态
t1 .start ( ) ;
t2 .start ( ) ;
}
}
控制台的输出结果为:
从结果当中我们可以看到,在多线程的应用程序当中,线程如何调用,是由虚拟机决定的。
注意:如果你的操作量太少,比如循环次数太少,那你可以看不到这个效果!
三、sleep
当我们线程执行完某一操作之后,要求先停下来,之后才继续进行,那此时我们将需要让线程休眠,由运行态转为可阻塞状态。比如,我们现在要编写一个每隔一秒钟输入一个数字,输出的数字是从100到999,那我们可以每输出一个数字之后,让线程休眠,由运行态转化为阻塞状态。
/**
* 使用继承方式的线程实现.
*
* @author <a href="http://www.suneca.com">zizz</a>
*
* @Create-Time:2008 下午10:25:33
*/
public class MyThread extends Thread {
public MyThread ( ) {
}
public MyThread (String name ) {
super (name ) ;
}
public void run ( ) {
//循环输出1 到 100
for ( int i =100 ;i < =999 ;i + + ) {
System .out .println (i ) ;
try {
//线程休眠,由运行态转化为阻塞状态
sleep (1000 ) ;
} catch (InterruptedException e ) {
e .printStackTrace ( ) ;
}
}
}
public static void main (String [ ] args ) {
//创建一个线程实例
MyThread t1 = new MyThread ( "T1" ) ;
//线程进入运行态
t1 .start ( ) ;
}
}
sleep(1000)表示线程休眠1秒钟!那线程休眠一秒钟之后是否马上就进入运行状态呢?不是的!从线程状态图我们可以看到,线程由阻塞状态并不是马上就进入运行状态,而是先进入可运行态,最后,由线程调度器进行调度。所以我们实现这个代码,严格来讲,是错的!谁也没有办法确保就刚好是一秒钟的时间输出一次!因为对于JAVA来讲,它也是运行于操作系统上的一个进程,操作系统此时有很多进程都是处于运行态!