美文网首页
004--【并发】Thread和Runnable对比分析

004--【并发】Thread和Runnable对比分析

作者: 糖纸疯了 | 来源:发表于2020-07-19 14:27 被阅读0次

    1、写在前面

    在此记录,以备遗忘


    2、核心要点

    2.1、Thread和Runnable哪一个更好

    2.2、Runable的优势-多线程内部数据共享

    2.3、启动顺序和执行结果顺序

    2.4、创建线程的疑惑:new Thread()和new Thread(Runnable接口实现类对象)的区别


    3、具体操作

    3.1、Thread和Runnable哪一个更好

    3.1.1、源码分析

    核心源码如下【进行过代码裁剪】:继承于Thread并实现它的run方法能创建一个线程,实际这个run方法就是Runnable所提供的代理对象所有的,因此我们可以得到Runnable的全部优点

    public class Thread implements Runnable {
        private Runnable target;
        private native void start(){
            @Override
            public void run() {
                if (target != null) {
                    target.run();
                }
            }
        }
    }
    

    3.1.2、Runable的优势总结

    1.【多线程内部数据共享】适合多个相同程序代码的线程去处理同一个资源(多线程内的数据共享)
    2.【继承】避免java特性中的单根继承限制
    3.【解耦】增加程序健壮性,数据被共享时,仍然可以保持代码和数据的分离和独立
    4.【设计】更能体现java面向对象的设计特点


    3.2、Runable的优势-多线程内部数据共享

    3.2.1、错误的线程并发案例【Thread实现】

    每个线程拥有自己的变量,线程之间没有共享数据

    public class Test03ThreadMain extends Thread {
        private int count = 5;
    
        @Override
        public void run() {
            for (int i = 0; i < 7; i++) {
                if (count > 0) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        System.out.println(Thread.currentThread().getName() + "----currentIndex:" + (count--));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            Test03ThreadMain h1 = new Test03ThreadMain();
            Test03ThreadMain h2 = new Test03ThreadMain();
            Test03ThreadMain h3 = new Test03ThreadMain();
            h1.start();
            h2.start();
            h3.start();
        }
    }
    

    3.2.2、正确的线程并发案例【Runable实现】

    public class Test03ThreadRunable implements Runnable{
        private int count = 5;
    
        @Override
        public void run() {
            for (int i = 0; i < 7; i++) {
                if (count > 0) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        System.out.println(Thread.currentThread().getName() + "----currentIndex:" + (count--));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        // 一个执行任务,让多个线程进行执行
        public static void main(String[] args) {
            Test03ThreadRunable runable = new Test03ThreadRunable();
            new Thread(runable, "1号窗口").start();
            new Thread(runable, "2号窗口").start();
            new Thread(runable, "3号窗口").start();
        }
    }
    

    3.3、启动顺序和执行结果顺序

    尽管启动线程的顺序是有序的,但是执行的顺序并非是有序的。也就是说,1号线程并不一定是第一个将自己名字输出到控制台的线程。这是因为线程是并行执行而非顺序的。【Jvm和操作系统一起决定了线程的执行顺序,他和线程的启动顺序并非一定是一致的。】


    3.4、创建线程的疑惑:new Thread()和new Thread(Runnable接口实现类对象)的区别

    参考博客:new Thread()和new Thread(Runnable接口实现类对象)的区别

    public class ThreadDemo2 {
        public static void main(String[] args) {
            // 创建Ruanbel对象【Thread也是Runable的实现】
            myThread myThread=new myThread();
            myThread.setName("B");
            // 创建Thread进行执行
            Thread thread=new Thread(myThread);
            thread.setName("A");
            thread.start();
        }
    }
    
    class myThread extends Thread{
        @Override
        public void run() {
            System.out.println("返回正在执行该代码的线程名称:"+Thread.currentThread().getName());
            System.out.println("当前线程对象的名称:"+this.getName());
        }
    }
    

    执行结果:

    • 返回正在执行该代码的线程名称【Thread.currentThread().getName())】:A
    • 当前线程对象的名称【this.getName()】:B

    执行结果分析:

    • 1)正常代码中都是使用Thread.currentThread().getName()),所以无论Runable执行的名称是什么,都不会影响我们对线程名称的打印
      -2)查看源码:target指向的【传入Thread的Runable对象】,所有用this进行打印,返回的是Runbale的名称【Runable本身没有名称,但是实现类Thread有名称,所以如果Thread有名称,就直接被this.name打印出来】
    • 3)Thread.currentThread()代指的逻辑就是new Thread(),所以打印A就很好理解了

    4、课后习题

    4.1、Thread和Runnable对比分析?从代码层面进行解析

    参考本文的3.1章节

    4.2、多线程内部数据共享,用代码进行实现


    5、参考网址

    相关文章

      网友评论

          本文标题:004--【并发】Thread和Runnable对比分析

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