zoukankan      html  css  js  c++  java
  • 彻底理解Runnable和Thread的区别

    昨天去面试,面试官问了一个问题:Runnable和Thread有什么区别,因为针对这个问题以前有背过,并且网上大多数都是这些结论,所以脱口而出:

    1.Thread有单继承的问题;
    2.Runnable便于实现资源共享,而Thread不能;
    

    然而面试官好像并没有什么表示。之后结束后我就找了一下度娘,得到了这篇文章:
    https://blog.csdn.net/zhaojianting/article/details/97664370

    突然发现“Runnable便于实现资源共享”这一优点好像并不合理,以下是我的代码实现。

    使用Thread实现多线程

    public class MyThread extends Thread {
    
        private int ticket = 5;
    
        @Override
        public void run() {
            while (true) {
                System.out.println("Thread ticket = " + ticket--);
                if (ticket < 0) {
                    break;
                }
            }
        }
    
    }
    
    public class Test {
        public static void main(String[] args) {
    
                //Test Thread
    
            new MyThread().start();
            new MyThread().start();
    
        }
    }
        
    执行结果如下:
    Thread ticket = 5
    Thread ticket = 4
    Thread ticket = 3
    Thread ticket = 2
    Thread ticket = 1
    Thread ticket = 0
    Thread ticket = 5
    Thread ticket = 4
    Thread ticket = 3
    Thread ticket = 2
    Thread ticket = 1
    Thread ticket = 0
    

    并不能实现资源共享,跟以前背的面试题答案一样;但真的是这样吗?我们仔细看一下,代码中我们创建了两个MyThread对象,每个对象都有自己的ticket成员变量,当然会多卖1倍。现在我们重新测试一下,请看测试代码:

    public class Test {
        public static void main(String[] args) {
    
                //Test Thread
    
            MyThread t1 = new MyThread();
            new Thread(t1).start();
            new Thread(t1).start();
        }
    }
    
    测试结果如下:
    Thread ticket = 5
    Thread ticket = 4
    Thread ticket = 3
    Thread ticket = 2
    Thread ticket = 1
    Thread ticket = 0
    Thread ticket = -1
    

    可以看到这次我们只创建了一个MyThread对象,并没出现卖两倍票的情况,Thread也可以实现资源共享。

    因为多线程访问同一变量会有并发问题(需要加锁),所以Thread正确的写法如下:

    public class MyThread extends Thread {
    
        private int ticket = 5;
    
        @Override
        public void run() {
            if (ticket > 0) {
                synchronized (this) {
                    if (ticket > 0) {
                        while (true) {
                            System.out.println("Thread:" + Thread.currentThread().getName() + "--Thread ticket = " + ticket--);
                            if (ticket < 0) {
                                break;
                            }
                        }
                    }
                }
            }
        }
    
    }
    
    public class Test {
        public static void main(String[] args) {
    
                //Test Thread
    
            MyThread t1 = new MyThread();
            new Thread(t1).start();
            new Thread(t1).start();
            new Thread(t1).start();
            new Thread(t1).start();
            new Thread(t1).start();
            new Thread(t1).start();
        }
    }
    
    执行结果如下:
    Thread:Thread-1--Thread ticket = 5
    Thread:Thread-1--Thread ticket = 4
    Thread:Thread-1--Thread ticket = 3
    Thread:Thread-1--Thread ticket = 2
    Thread:Thread-1--Thread ticket = 1
    Thread:Thread-1--Thread ticket = 0
    

    现在看Thread和Runnable的源码:

    
    public
    class Thread implements Runnable {
        /* Make sure registerNatives is the first thing <clinit> does. */
        private static native void registerNatives();
        static {
            registerNatives();
        }
    
        private volatile String name;
        private int            priority;
        private Thread         threadQ;
        private long           eetop;
        
        
    
    @FunctionalInterface
    public interface Runnable {
        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }
    
    

    结论:其实Thread也就是实现了Runnable接口,提供了更多的方法而已。所以说Thread与Runnable并没有什么区别。如果硬要说有什么区别的话,那就是类与接口的区别,继承与实现的区别。另外最重要的是,学习的时候不要忘了思考哦!

  • 相关阅读:
    火狐浏览器处理jquery中:header的问题。
    兼容IE与FF的childNodes问题(ff childNodes)
    前端开发的几个辅助类工具
    固定 vs. 流动 vs. 弹性:哪种布局更适合你?
    由浅入深漫谈margin属性
    Firefox 的 Jetpack 扩展案例分析:Gmail 邮件提醒
    jQuery性能优化
    浅谈.NET中可用的定时器和计时器【上篇】
    现有分布式技术(socket、.net remoting、asp.net webservice、WSE、ES)和wcf的比较及优势
    Mono for Android 4.2初探
  • 原文地址:https://www.cnblogs.com/J-Simon/p/11470758.html
Copyright © 2011-2022 走看看