美文网首页基础知识
多线程两种实现方式的区别

多线程两种实现方式的区别

作者: 秋笙fine | 来源:发表于2019-01-16 02:14 被阅读54次

    这是一道面试题。这两种方式有哪种区别?
    Runnable将数据共享这一特点完美诠释。

    首先一定要明确的是,使用我们的Runnable接口与Thread类相比,解决了单继承的定义局限,所以在优先级上已经确定使用Runnable接口。
    首先看jdk源码中Thread类定义:

    public class Thread extends Object implements Runnable
    

    发现Thread类实现了Runnable接口,那么这样一来就变为了以下形式。

    image.png

    我们可以看出,Runnable接口实现多线程其实很像代理模式的应用。很好的起到了设计模式中原则中的迪米特原则。之所以是"像",因为如果是代理设计模式,那么客户端调用的应该是接口里面提供的run()方法。

    除了以上联系之外,使用Runnable接口可以比Thread类更好的描述出数据共享这一个概念,此时的数据共享指的是多个线程访问同一资源的操作。
    范例:观察代码(每一个线程对象都必须通过start()启动)

    package TestDemo;
    
    
    
    class MyThread extends Thread{
        private int ticket=10;//这里的变量会压入局部变量表 因为并没有用static声明
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if(this.ticket>0){
                    System.out.println("sell,ticket="+this.ticket--);
                }
            }
        }
    }
    
    public class TestDemo{
        
        public static void main(String[] args) {
            MyThread thread1=new MyThread();
            MyThread thread2=new MyThread();
            MyThread thread3=new MyThread();
    
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }
    
    image.png
    结果三个thread类都在卖各自的10张票,这是由于我们并没有给ticket设置为static变量,所以这个数据没有被录入元数据区,而被压入了局部变量表,在执行实例化操作后,各自生成了一块堆内存指向,此时并不存在数据共享这一概念。

    在JVM内存模型基础上,我们可以看这张基于多线程的内存模型。

    image.png
    也很好的诠释了这一点。而Runnable就完美实现了这张内存模型图,我们可以把主存看作是MyThread类中的元数据,三个new Thread类匿名内部类对象实例看作3块工作内存。

    范例:利用Runnable实现。

    package TestDemo;
    
    
    
    class MyThread implements Runnable{
        private int ticket=10;//这里的变量会压入局部变量表 因为并没有用static声明
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if(this.ticket>0){
                    System.out.println("sell,ticket="+this.ticket--);
                }
            }
        }
    }
    
    public class TestDemo{
        
        public static void main(String[] args) {
            MyThread mt=new MyThread();
            new Thread(mt).start();
            new Thread(mt).start();
            new Thread(mt).start();
        
        }
    }
    
    image.png
    原理分析:这是由于三个不同的栈都指向了同一块堆内存对象,确保了他们操作的是同一个实例化对象。

    因而当多个线程访问同一资源时候,我们使用Runnable更好的描述了数据共享这个概念(本质上是JVM虚拟栈是否指向同一块堆内存)

    总结:请解释Thread类与Runnable接口实现多线程的区别(请解释多线程两种实现方式区别)?

    Thread类是Runnable接口的子类,使用Runnable接口实现多线程可以避免单继承的局限性。
    Runnable接口实现的多线程可以比Thread类实现的多线程更加清楚的描述数据共享的概念(本质上是JVM虚拟栈是否指向同一块堆内存)
    可以将JVM内存布局以及基于多线程的内存模型画出来。

    以及将两种多线程实现方式,白板编程出来。

    关注公众号Code In Java,Java学习图谱,数据结构与算法资料等各种资料都可以在后台获取。等你哦~

    相关文章

      网友评论

        本文标题:多线程两种实现方式的区别

        本文链接:https://www.haomeiwen.com/subject/mvcpdqtx.html