Thread 和Runnable 的区别
学了这么久的多线程,始终有一点迷惑
往线程池里面提交的时候,提交的是一个实现了Runnable接口的对象,本来提交的时候就是一个Runnable,那么怎么实现线程复用。
产生这个迷惑的原因是没有弄明白Thread 和Runnable的区别。
java中真正的线程执行类是Thread
Runnable(可运行的)只是一个接口,中间定义了run()方法,实现了这个接口的类,实现了run()方法,通过把这个实现类交给Thread对象去运行。
thread.start()方法里调用了start0()这个native函数来实现.start()函数的注释上写着,java虚拟机会自动调用这个线程的run()方法,然并卵。
请看thread里面的run()怎么写的,如果target(一个Runnable实例对象)不为空,他就调用其中的run()方法。我相信start0()这个native方法里面肯定取调用了run()方法。见如下的代码
也可以把Runnable理解成只是JDK给出的一个标识性接口而已。看网上说了那么多都是浮云。
|
自己写一个线程池
大家都知道要用线程池,也有一些讲Executor框架的博客之类的,咋一看理解起来不成问题,自己准备参照网上的一些例子,写一个最简单的线程池
线程池说白了,一个List池子里面有一堆的Thread对象,然后提交一个Runable对象,这时候,从List池子里面取一个Thread对象来调用Runnable对象的run()方法而已! Thread才是真正的线程对象,他的创建才是需要开销的。
线程池类
|
线程池中的线程类
为什么需要定义自己的线程? 因为线程池里面的线程,执行完提交的任务之后,还需要复用(不能run()方法执行完就结束了)。所以需要自定线程来管理当前线程的生命周期。
只要上面两个类,一个最基本的线程池就建立好了(每次提交任务的时候,如果有空闲线程就使用空闲线程,否则创建新的线程),每次只要使用submit()方法提交一个任务就好了。
下面使用一个例子,来测试一下
例子
两个任务类
|
Client类
|
结果
我们提交了100个任务,可是最后只启动了42个线程,这就是线程池。Executor框架中的几种线程池都差不多是这种套路,只是控制策略根加的多。