一、任务和线程
《thinking in java》中专门有一小节中对线程和任务两个概念进行了具体的区分,这也恰好说明任务和线程是有区别的。
正如前文所提到的,任务只是一段代码,一段要达成你目的的代码,这段代码写在哪,怎么写其实无所谓,只是因为你希望java的多线程机制能够识别并调用你编写的任务,所以规定了Runnable接口,让你的任务来实现该接口,把你想做的工作在实现该接口的run方法中实现。
那么,已经定义了任务类,那任务和线程有什么关系呢?
java的线程是用来驱动任务执行的,也就是说你得把任务挂载到一个线程上,这样该线程才能驱动你定义的任务来执行。
二、定义线程
1.显示的定义线程的过程就是将任务附着到线程的过程。线程Thread自身并不执行任何操作,它只是用来被多线程机制调用,并驱动赋予它的任务。
如前次文章提到的任务类定义如下:
public class Task implements Runnable { protected int countDown = 10; private static int taskCount = 0 ; private final int id = taskCount++; public Task(){} public Task(int countDown){ this.countDown = countDown; } public String status(){ return "#"+id+"("+(countDown>0?countDown:"Task!")+"). "; } @Override public void run() { while(countDown-->0){ System.out.print(status()); Thread.yield(); } } }
声明线程并将任务附着到该线程上:
Thread t = new Thread(new Task());
这样,任务就附着给了线程,下面就是让线程启动,只需要如下的调用:
t.start();
至此,线程声明ok。
有时,我会想,是不是像任务和线程的概念分离一样,此时只是声明了线程,而java的线程机制并不会调用该线程运行,还需要特殊的调用才能实现多线程执行。但是下面的一段代码告诉我,Thread类的start方法就是触发了java的多线程机制,使得java的多线程能够调用该线程
public static void main(String[] args){ Thread t = new Thread(new Task()); t.start(); System.out.println("Waiting for Task"); }
输出结果如下:
Waiting for Task #0(9). #0(8). #0(7). #0(6). #0(5). #0(4). #0(3). #0(2). #0(1). #0(Task!).
先输出“Waiting for Task”证明调用完start()方法后,立即返回了主程序,并开始执行下面的语句。而你声明的t线程已经去被java的多线程机制调用,并驱动着它的任务运行了。
2.补充
想看到更多的线程任务运行,可以用下面的这段代码
public static void main(String[] args){ for(int i = 0 ; i < 5 ; i++){ new Thread(new Task()).start(); } System.out.println("Waiting for Task"); }
输出如下:
Waiting for Task #0(9). #2(9). #4(9). #0(8). #2(8). #4(8). #0(7). #2(7). #4(7). #0(6). #2(6). #4(6). #0(5). #2(5). #4(5). #0(4). #2(4). #4(4). #3(9). #2(3). #4(3). #2(2). #4(2). #2(1). #4(1). #2(Task!). #4(Task!). #1(9). #0(3). #0(2). #0(1). #0(Task!). #3(8). #1(8). #3(7). #1(7). #3(6). #1(6). #3(5). #3(4). #3(3). #3(2). #3(1). #3(Task!). #1(5). #1(4). #1(3). #1(2). #1(1). #1(Task!).
上面的输出说明不同任务的执行在线程被换进换出时混在了一起——由线程调度器自动控制。不同版本的jdk线程调度方式不同,所以产生的结果也不相同。
这里涉及了垃圾回收器的一个问题,每个Thread都注册了它自己,因此确实有一个对它的引用,而且在它的任务退出其run并死亡之前,垃圾回收器无法清除它。
注:以上代码均来自《thinking in java》,内容大部分是个人理解和总结,如有错误请各位指正