Runnable和Thread的区别
前言
Runnable和Thread广泛用于多线程的开发,关于Runnable和Thread的区别,在网上搜了很多帖子或文章,感觉解释得都不甚明了,这里从使用的角度分析一下两者的区别。
正文
1、Runnable例子-不能并发
package com.hf.test.jar;
public class RunnableTest {
/**
* 定义runnable实现类
* @author hf
*
*/
public class MyRunnable implements Runnable{
String objectid = null;
public MyRunnable(String objid){
objectid = objid;
}
public void run(){
int i =0;
while(i<100){
System.out.println(objectid + "-" + Thread.currentThread().getId() + "-A" + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
};
/**
* 测试多个Runnable
*/
public void test1(){
for(int i=0;i<3;i++){
new MyRunnable("instance" + i).run();
}
}
public static void main(String[] args) {
RunnableTest rt = new RunnableTest();
rt.test1();
}
}
结果(部分):
instance0-1-A87
instance0-1-A88
instance0-1-A89
instance0-1-A90
instance0-1-A91
instance0-1-A92
instance0-1-A93
instance0-1-A94
instance0-1-A95
instance0-1-A96
instance0-1-A97
instance0-1-A98
instance0-1-A99
instance1-1-A0
instance1-1-A1
instance1-1-A2
instance1-1-A3
instance1-1-A4
instance1-1-A5
可以看到3个Runnable按顺序执行,并未能并发执行。一个Runnable执行完了,再执行下一个Runnable。
使用JVisualVM监控工具监控到的结果显示,并未开启新的进程,仍然在主线程上执行。
2、Thread例子-不能并发
package com.hf.test.jar;
public class ThreadTest1 {
public class MyThread extends Thread{
String objectid = null;
public MyThread(String objid){
objectid = objid;
}
public void run(){
int i =0;
while(i<100){
System.out.println(objectid + "-" + Thread.currentThread().getId() + "-A" + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
};
public void test1(){
for(int i=0;i<3;i++){
new MyThread("instance" + i).run();
}
}
public static void main(String[] args) {
ThreadTest1 rt = new ThreadTest1();
rt.test1();
}
}
结果(部分):
instance0-1-A92
instance0-1-A93
instance0-1-A94
instance0-1-A95
instance0-1-A96
instance0-1-A97
instance0-1-A98
instance0-1-A99
instance1-1-A0
instance1-1-A1
instance1-1-A2
instance1-1-A3
instance1-1-A4
instance1-1-A5
instance1-1-A6
instance1-1-A7
可以看到,Thread方式并未以并发的方式运行,仍然和例1一样是顺序执行。
3、例子3-Thread-start启动-可以并发
我们将Thread的执行方法由run()改为start(),然后再做测试。
代码:
package com.hf.test.jar;
public class ThreadTest1b {
public class MyThread extends Thread{
String objectid = null;
public MyThread(String objid){
objectid = objid;
}
public void run(){
int i =0;
while(i<100){
System.out.println(objectid + "-" + Thread.currentThread().getId() + "-A" + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
};
public void test1(){
for(int i=0;i<3;i++){
new MyThread("instance" + i).start();
}
}
public static void main(String[] args) {
ThreadTest1b rt = new ThreadTest1b();
rt.test1();
}
}
结果(部分):
instance0-10-A0
instance2-12-A0
instance1-11-A0
instance1-11-A1
instance2-12-A1
instance0-10-A1
instance1-11-A2
instance0-10-A2
instance2-12-A2
instance1-11-A3
instance0-10-A3
instance2-12-A3
instance1-11-A4
可见,Thread以并发的方式运行,3个线程交替执行。通过JVisiualVM监控工具,发现确实多了3个线程:
那么实现Runnable的类可不可以并发执行呢?
4、Runnable-可以并发
将Runnable类用Thread包裹,并使用Thread的start()方法,则可以实现Runnable类并发执行。
代码:
package com.hf.test.jar;
import java.io.Serializable;
public class RunnableTest3 {
/**
* 定义runnable实现类
* @author hf
*
*/
public class MyRunnable implements Runnable{
String objectid = null;
public MyRunnable(String objid){
objectid = objid;
}
public void run(){
int i =0;
while(i<100){
System.out.println(objectid + "-" + Thread.currentThread().getId() + "-A" + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
};
/**
* 测试多个Runnable
*/
public void test1(){
for(int i=0;i<3;i++){
new Thread(new MyRunnable("instance" + i)).start();
}
}
public static void main(String[] args) {
RunnableTest3 rt = new RunnableTest3();
rt.test1();
}
}
结果(部分):
instance0-10-A0
instance2-12-A0
instance1-11-A0
instance0-10-A1
instance1-11-A1
instance2-12-A1
instance2-12-A2
instance1-11-A2
instance0-10-A2
instance2-12-A3
instance1-11-A3
instance0-10-A3
instance2-12-A4
instance0-10-A4
总结:
1、Runnable和Thread类均可以实现并发执行,但Runnable并发执行时需要依赖于Thread。
2、要实现并发执行,要执行Thread类的start()方法,而不是run()方法。
3、Runnable在实现多继承上有优势,而Thread则无法再使用implement实现多继承。