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实现多继承。

 

 

 

 

 

 

posted @ 2019-09-20 09:51  hongweigg  阅读(37)  评论(0编辑  收藏  举报