昨天去面试,面试官问了一个问题: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并没有什么区别。如果硬要说有什么区别的话,那就是类与接口的区别,继承与实现的区别。另外最重要的是,学习的时候不要忘了思考哦!

彻底理解Runnable和Thread的区别的更多相关文章

  1. Java中Runnable和Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...

  2. Android笔记——Handler Runnable与Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...

  3. Android开发笔记之:Handler Runnable与Thread的区别详解

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一 个类只要继承了Thread类同时覆写了本类中的run( ...

  4. Runnable和Thread的区别 (转)

    在java中可有两种方式实现多线程,一种是继承 Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的 run ...

  5. 【转】java线程系列---Runnable和Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...

  6. java线程系列---Runnable和Thread的区别 (转载)

    转自:http://blog.csdn.net/wwww1988600/article/details/7309070 在java中可有两种方式实现多线程,一种是继承 Thread类,一种是实现Run ...

  7. Java中Runnable和Thread的区别(转)

    http://developer.51cto.com/art/201203/321042.htm 第一种方式:使用Runnable接口创建线程 第二种方式:直接继承Thread类创建对象 使用Runn ...

  8. runnable和thread的区别

    一是写一个类继承自Thread类,然后重写里面的run方法,用start方法启动线程二是写一个类实现Runnable接口,实现里面的run方法,用new Thread(Runnable target) ...

  9. Runnable和Thread区别和比较

    在很多博客中用这样一个例子来说明 Runnable更容易实现资源共享,能多个线程同时处理一个资源. 看代码: public static void main(String[] args) { new ...

随机推荐

  1. pipelinewise 学习二 创建一个简单的pipeline

    pipelinewise 提供了方便的创建简单pipeline的命令,可以简化pipeline 的创建,同时也可以帮我们学习 生成demo pipeline pipelinewise init --n ...

  2. golang 配置goproxy 几个可选的地址

    对于golang 语言的开发,对于国内来说有点被动,需要想各种方法,一般的解决方法如下: 使用代理工具(翻墙) 配置goproxy 目前发现的几个不错的goproxy 阿里云 配置如下:   expo ...

  3. nginx 篇

    nginx 安装 下载必要组件 nginx下载地址 http://nginx.org/en/download.html pcre库下载地址,nginx需要 http://sourceforge.net ...

  4. TCP三次握手的过程,accept发生在三次握手的哪一个阶段?

    答案是:accept过程发生在三次握手之后,三次握手完成后,客户端和服务器就建立了tcp连接并可以进行数据交互了.这时可以调用accept函数获得此连接. TCP Accept总结 TCP Accep ...

  5. kernel 获取ntoskrnl.exe基址

    标题: kernel shellcode之寻找ntoskrnl.exe基址 http://scz.617.cn:8/windows/201704171416.txt 以64-bits为例,这是Eter ...

  6. MySql的执行计划

    一.什么是数据库执行计划: MySQL执行计划是sql语句经过查询优化器后,查询优化器会根据用户的sql语句所包含的字段和内容数量等统计信息,选择出一个执行效率最优(MySQL系统认为最优)的执行计划 ...

  7. 为 Nginx 添加 HTTP 基本认证(HTTP Basic Authentication)

    针对sudo apt-get install命令安装的nginx(默认会有/etc/nginx/conf.d) sudo apt-get install nginx 生成密码 printf " ...

  8. ModuleNotFoundError: No module named 'pymysql'

    出现此提示表示系统中没有安装PyMySQL,可以通过pip PyMySQL进行安装. 安装之后,执行import pymysql仍然不可用! why? 检查后发现系统中存在python2与python ...

  9. 在 RPA10.X 运行异常,RPA9 却正常的问题处理

    一.现象 RPA10.X 在一些极少数 win7/win10 环境中一运行就崩溃或无运行结果. 二.原因 出现上述现象已经确定是OPenGL 驱动兼容性造成的. 三.解决方法 方法一 只要把流程的管理 ...

  10. Java一行代码

    1.整数格式化成0X 的形式字符串 String hour=String.format("%02d", txtWaringTime.getCurrentHour()); Strin ...