彻底理解Runnable和Thread的区别
昨天去面试,面试官问了一个问题: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的区别的更多相关文章
- Java中Runnable和Thread的区别
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...
- Android笔记——Handler Runnable与Thread的区别
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...
- Android开发笔记之:Handler Runnable与Thread的区别详解
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一 个类只要继承了Thread类同时覆写了本类中的run( ...
- Runnable和Thread的区别 (转)
在java中可有两种方式实现多线程,一种是继承 Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的 run ...
- 【转】java线程系列---Runnable和Thread的区别
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...
- java线程系列---Runnable和Thread的区别 (转载)
转自:http://blog.csdn.net/wwww1988600/article/details/7309070 在java中可有两种方式实现多线程,一种是继承 Thread类,一种是实现Run ...
- Java中Runnable和Thread的区别(转)
http://developer.51cto.com/art/201203/321042.htm 第一种方式:使用Runnable接口创建线程 第二种方式:直接继承Thread类创建对象 使用Runn ...
- runnable和thread的区别
一是写一个类继承自Thread类,然后重写里面的run方法,用start方法启动线程二是写一个类实现Runnable接口,实现里面的run方法,用new Thread(Runnable target) ...
- Runnable和Thread区别和比较
在很多博客中用这样一个例子来说明 Runnable更容易实现资源共享,能多个线程同时处理一个资源. 看代码: public static void main(String[] args) { new ...
随机推荐
- LeetCode 911. Online Election
原题链接在这里:https://leetcode.com/problems/online-election/ 题目: In an election, the i-th vote was cast fo ...
- 常用方法 DataTable转换为Entitys
备注:摘自网上 有附地址 public static List<T> DataTableToEntities<T>(this DataTable dt) where T : c ...
- 鸿蒙OS与微内核
目前主流面向个人端操作系统都不是像鸿蒙一样采用微内核的,或许在这些操作系统上诞生时面对的需求场景用微内核是行不通的.但在当前场景下是不是能走通要实际验证才知道.面对当前操作系统已成熟的市场生态.专利技 ...
- pycharm配置默认代码和注释模板
有人问,在pycharm新建python文件时,文件开头的注释每次都要重复写,能不能配置成模板?其实pycharm本身自带此功能 在pycharm菜单栏找File -> settings -&g ...
- mysql-创建用户报错ERROR 1396 (HY000): Operation CREATE USER failed for 'root'@'localhost'
创建用户: create user ‘test’@’%’ identified by ‘test’; 显示ERROR 1396 (HY000): Operation CREATE USER faile ...
- hive删除空分区
当hive中分区字段有NULL值时,hive会使用dynamic partition,数据会放到一个特殊的分区,这个分区由参数“hive.exec.default.partition.name”控制, ...
- Java基础 awt Frame 设置窗体的大小 位置 可见性
JDK :OpenJDK-11 OS :CentOS 7.6.1810 IDE :Eclipse 2019‑03 typesetting :Markdown code ...
- 闭包(python)
1.闭包的理解 我们可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,且称之为外函数和内函数,外函数返回值是内函数的引用,此时就构成了闭包. 2. 闭包的格式 下面用伪代码进行闭包格式的描 ...
- Ubuntu 16.04 Roboware Turtlesim 测试
博客参考:https://www.jianshu.com/p/5509c8ba522b?utm_campaign 利用Turtlesim,编写简单的消息发布器和订阅器 1. Twist消息,它的Top ...
- 创建Observable序列
1. just()方法 该方法通过传入一个默认值来初始化 下面样例我们显示地标注出了observable的类型为Observable, 即指定了这个Observable所发出的事件携带的数据类型必须是 ...