zoukankan      html  css  js  c++  java
  • 并发编程之多线程基础-Thread和Runnable的区别及联系(二)

    上篇文章讲述了创建线程的常用方式

    本篇主要分析一下Thread和Runnable两种方式创建线程的区别及联系

    联系:

    ▶Thread类实现了Runable接口。

    ▶都需要重写里面Run方法。

    区别:

    ▶Thread方式不支持多继承,Runnable方式支持多个实现

    ▶Runnable更容易实现资源共享,能多个线程同时处理一个资源。

    疑惑分享:

    本人在理解他们区别的时候

    考虑到Thread类本身就是Runnable的实现类

    所以产生了一个疑惑:-

    为什么Runnable可以实现共享而Thread却不行呢

    疑惑代码:

    class Thread1 extends Thread {
    int i = 100;
    @Override
    public void run() {

    while (i > 0) {
    try {
    Thread.sleep(40L);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    synchronized (this) {

    /*synchronized 不要直接放在run方法 应该放到循环里面 这样多个线程在循环的时候每次都能竞争锁 从而实现交替执行 否则一个线程执行完了另一个线程就没有执行的机会了*/
    if (i > 0) {

    /*

    1.加判断是为了 如果当i=1的时候 此时两个线程都执行到了这里  一个线程得到锁进行减一操作那么i变为0 此时第二个线程再输出就会把0输出出来

    2.第二个线程能够及时读取到i的值是由于synchronized既可以实现原子性又可以实现可见性*/

    System.out.println(Thread.currentThread().getName() + "i:" + i);
    i--;}}}
    }}

    public class TestThread {

      public static void main(String[] args) {

         Thread1 te1 = new Thread1();

         Thread t1 = new Thread(te1, "window1");

         Thread t2 = new Thread(te1, "window2");

         t1.start();

         t2.start();

      }

    }

    下面我们就来聊一聊(有共同疑惑的朋友们可以参考一下):

    首先我们要清楚Thread和Runnable两种方式的本质区别在哪里

    我们知道无论使用哪种方式最终都会通过 Thread类对象调用start方法进行开启线程

    本质的区别就在于:

    Thread方式是调用无参构造方法

    Runnable方式是调用带有Runnable参数的有参构造方法

    我们说过Thread类实现了Runable接口

    以上疑惑代码中就是向Thread构造方法中传递了一个Tel1参数

    看似与Runnable没有关系

    但实质上是属于常说的Runnable方式调用

    对应源码:Thread(Runnable target, String name)

    那么有参和无参有什么区别是什么呢,为什么runnable能实现资源共享:

    参考源码:

    this.target = paramRunnable;

    public void run()

      {

        if (this.target != null)

          this.target.run();

      }

    有参:

    如果是参数中Runnable不为空

    那么Thread run方法中最终执行的方法实际上是传进来Runnable中的run方法

    所以使用Runnable方式 无论new出多少个Thread对象

    最终执行的任务都是一样的

    自然就实现了资源的共享

    无参:

    每次new出Thread对象

    他们对应的成员变量是互不影响的

    所以就不能达到资源共享的效果

    涉及知识点:

    JMM关于synchronized的两条规定:

      1)线程解锁前,必须把共享变量的最新值刷新到主内存中

      2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值

       (注意:加锁与解锁需要是同一把锁)

     通过以上两点,可以看到synchronized能够实现可见性。同时,由于synchronized具有同步锁,所以它也具有原子性

    温馨提示:

    ▶在学习过程中理解一些概念或者结论不清晰的时候,一定要亲自动手结合着代码去分析,不要片面的理解一些知识点,一定要搞清实质。

    ▶本文内容如有不妥,恳请指正。

  • 相关阅读:
    【leetcode】N叉树的前序遍历
    【leetcode】第 N 个泰波那契数
    【leetcode】下一个更大元素 I
    【leetcode】Nim 游戏
    【leetcode】非递减数列
    053-208
    053-211
    053-56
    053-53
    053-236
  • 原文地址:https://www.cnblogs.com/LoveShare/p/9782373.html
Copyright © 2011-2022 走看看