纠错!Thread 和 Runnable 之间数据共享问题

看博客要慎重

网上大多数博客的说法是这样的:
通过实现Thread类的线程之间数据不共享,而实现Runnable接口的线程之间数据共享。
我一直在想,这没有道理啊,Thread也是实现Runnable的,而Runnable里只有一个run方法,归根结底线程的操作均是操作Thread,那为什么会有区别呢?

直到某一天,我突然回过神,看了看所谓数据不共享的代码,突然明白了,废话少说上代码。

以下是众多博客下关于Thread和Runnable数据共享的例子:
实现Runnable

代码块一

public class Main {
    public static void main(String[] args) {
        demo2 demo = new demo2();
        Thread thread1 = new Thread(demo);
        Thread thread2 = new Thread(demo);
        Thread thread3 = new Thread(demo);
        Thread thread4 = new Thread(demo);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
class demo2 implements Runnable{
    int i=0;
    @Override
    public void run(){
        System.out.println(i);
        i++;
    }
}

其结果是
在这里插入图片描述
继承Thread:

代码块二

public class Main {
    public static void main(String[] args) {
        demo1 demo1 = new demo1();
        demo1 demo2 = new demo1();
        demo1 demo3 = new demo1();
        demo1 demo4 = new demo1();

        demo1.start();
        demo2.start();
        demo3.start();
        demo4.start();
    }
}
class demo1 extends Thread{
    int i=0;
    @Override
    public void run(){
        System.out.println(i);
        i++;
    }
}

其结果是:
在这里插入图片描述
看到这里是不是觉得继承Thread类的线程真的数据不共享?

那就大错特错了,看看上面继承Thread类的例子,它是怎么建立线程的?都是重复实例demo1,然后start,请问?一个类不同对象之间怎么共享变量?( 此处忽略静态变量 )

我笑了,如果按照这种写法,Runnable也可以数据不共享,如下:
代码块三

public class Main {
    public static void main(String[] args) {
        demo2 demo1 = new demo2();
        demo2 demo2 = new demo2();
        demo2 demo3 = new demo2();
        demo2 demo4 = new demo2();
        Thread thread1 = new Thread(demo1);
        Thread thread2 = new Thread(demo2);
        Thread thread3 = new Thread(demo3);
        Thread thread4 = new Thread(demo4);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
class demo2 implements Runnable{
    int i=0;
    @Override
    public void run(){
        System.out.println(i);
        i++;
    }
}

这段代码的结果为在这里插入图片描述
所以这就是一个错误,网上各种博客无脑抄的错误,所以正确方法是:
代码块四

public class Main {
    public static void main(String[] args) {
        demo1 demo = new demo1();
        Thread thread1 = new Thread(demo);
        Thread thread2 = new Thread(demo);
        Thread thread3 = new Thread(demo);
        Thread thread4 = new Thread(demo);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
class demo1 extends Thread{
    int i=0;
    @Override
    public void run(){
        System.out.println(i);
        i++;
    }
}

对同一对象创建线程,各个线程之间所有数据均共享。
有的人会说为什么要new Thread,这不是多此一举吗?是,如果没有变量共享要求,这样的确是多此一举,但是如果需要共享变量就必须这么写,而且
如果按照代码块二的写法,synchronize和volatile均失效,因为他们之间不存在数据共享,因为创建他们的对象均不是统一个对象那么为什么会要求不同对象之间数据共享呢?

综上,继承Thread类和实现Runnable接口均能实现数据共享,如果创建的线程所属于不同对象,那么无论你怎么做,你都无法共享非静态变量,神也帮不了你,但是如果你创建的多个线程均是由一个对象创建的,那么Thread和Runnable都可以实现数据共享

最后一句,看博客需谨慎,独立思考最重要!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值