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

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、参考网址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值