extend Thread 和 implements Runnable
一个Thread的实例只能产生一个线程
or:
同一实例(Runnable实例)的多个线程
look:
| public class Test { public static void main(String[] args) throws Exception{ MyThread mt = new MyThread(); mt.start(); mt.join(); Thread.sleep(3000); mt.start(); } } |
当线程对象mt运行完成后,我们让主线程休息一下,然后我们再次在这个线程对象上启动线程。结果我们看到:
Exception in thread "main" java.lang.IllegalThreadStateException
也就是这种线程对象一时运行一次完成后,它就再也不能运行第二次了。我们可以看一下它有具体实现:
| public synchronized void start() { if (started) throw new IllegalThreadStateException(); started = true; group.add(this); start0(); } |
一个Thread的实例一旦调用start()方法,这个实例的started标记就标记为true,事实中不管这个线程后来有没有执行到底,只要调用了一次start()就再也没有机会运行了,这意味着:
[通过Thread实例的start(),一个Thread的实例只能产生一个线程]
那么如果要在一个实例上产生多个线程(也就是我们常说的线程池),我们应该如何做呢?这就是Runnable接口给我们带来的伟大的功能。
| class R implements Runnable{ private int x = 0; public void run(){ for(int i=0;i<100;i++){ try{ Thread.sleep(10); }catch(Exception e){} System.out.println(x++); } } } |
正如它的名字一样,Runnable的实例是可运行的,但它自己并不能直接运行,它需要被Thread对象来包装才行运行:
| public class Test { public static void main(String[] args) throws Exception{ new Thread(new R()).start(); } } |
当然这个结果和mt.start()没有什么区别。但如果我们把一个Runnable实例给Thread对象多次包装,我们就可以看到它们实际是在同一实例上启动线程:
| public class Test { public static void main(String[] args) throws Exception{ R r = new R(); for(int i=0;i<10;i++) new Thread(r).start(); } } |
x是实例对象,但结果是x被加到了999,说明这10个线程是在同一个r对象上运行的。请大家注意,因为这个例子是在单CPU上运行的,所以没有对多个线程同时操作共同的对象进行同步。这里是为了说明的方便而简化了同步,而真正的环境中你无法预知程序会在什么环境下运行,所以一定要考虑同步。
到这里我们做一个完整的例子来说明线程产生的方式不同而生成的线程的区别:
| package debug; import java.io.*; import java.lang.Thread; class MyThread extends Thread{ public int x = 0; public void run(){ System.out.println(++x); } } class R implements Runnable{ |
上面10个线程对象产生的10个线程运行时打印了10次1。下面10个线程对象产生的10个线程运行时打印了1到10。我们把下面的10个线程称为同一实例(Runnable实例)的多个线程。
Java 多线程实现接口Runnable和继承Thread区别
看别人帖子,觉得不错,自己整理标记下http://blog.csdn.net/litaoshoujiao/article/details/8542859
目前Java中实现多线程可通过实现Runnable接口或者继承Thread,他们之间存在不少区别,建议使用Runnable;
首先建立多线程,
extend Thread类:
实现Runnable接口:
测试程序:
区别与联系:
1, 一个类只能继承一个父类,存在局限;一个类可以实现多个接口
2, 在实现Runable接口的时候调用Thread的Thread(Runnable run)或者Thread(Runnable run ,String name)构造方法创建进程时,使用同一个Runnable实例,如上程序中使用的都是rt,则建立的多线程的实例变量也是共享的;
但是通过继承Thread类是不能用一个实例建立多个线程;
故而实现Runnable接口适合于资源共享;
当然,继承Thread类也能够共享变量,能共享Thread类的static变量;
3, Runnable接口和Thread之间的联系:
public class Thread extends Object implements Runnable
可以看出Thread类也是Runnable接口的子类;
下面大家可以直接去看Thread的源代码。
extend Thread 和 implements Runnable的更多相关文章
- extends Thread 与 implements Runnable 的区别
http://blog.csdn.net/zhikun518/article/details/7526298 1.通过实现Runnable接口创建线程 (1).定义一个类实现Runnable接口,重写 ...
- Java 中的“implements Runnable” 和“extends Thread”(转)
知识点 “implements Runnable” 和“extends Thread”的不同 具体分析 最近在学习Android中的Handler消息传递机制时,创建新线程有两种方式:一种是实现Run ...
- Java 中的“implements Runnable” 和“extends Thread”
知识点 “implements Runnable” 和“extends Thread”的不同 具体分析 最近在学习Android中的Handler消息传递机制时,创建新线程有两种方式:一种是实现Run ...
- java 多线程 继承Thread和实现Runnable的区别
1)继承Thread: public class ThreadTest extends Thread { private int count; private String name; public ...
- 线程的实现方法以及区别 extends Thread、implements Runable
/** 线程存在于进程当中,进程由系统创建. 创建新的执行线程有两种方法 注意: 线程复写run方法,然后用start()方法调用,其实就是调用的run()方法,只是如果直接启动run()方法, ...
- Thread类和Runnable接口实现多线程--2019-4-18
1.通过Thread实现 public class TestThread extends Thread{ public TestThread(String name) { super(name); } ...
- java中的线程问题(三)——继承Thread VS 实现Runnable的区别
从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口,如果一定要说它们有什么区别, ...
- 探Java多线程Thread类和Runnable接口之间的联系
首先复习一下Java多线程实现机制,Java实现多线程方法有如下这么几种: 1.继承了(extends)Thread类 2.实现了(implements)Runnable接口 也就是说 有如下两种情 ...
- Java 多线程之 Thread 类 和 Runnable 接口初步使用
目录 Thread 类 Thread之定义线程类 Thread之开启线程 Runnable 接口 Runnable 之定义线程类 Runnable 之开启线程 @ Thread 类 Thread 类是 ...
随机推荐
- B. Heaters ( Codeforces Round #515 (Div. 3) )
题解:对于每个点 i 来说,从 j = i + r - 1 开始往前找,如果找到一个 a [ j ] 是 1 ,那么就把它选上,但是我们需要判断交界处,也就是如果前面选的那个可以让这个点变温暖,就不用 ...
- 计蒜客——Nise-Anti-AK Problem
Nise-Anti-AK Problem #include<iostream> using namespace std; int b[1000]; int main() { ios::sy ...
- 关于移动虚拟机后,linux网卡启动异常问题解决
废话不多说,直接上解决办法. 首先执行命令:ifconfig -a 会发现原来是eth0, 而现在变成了eth1了 然后我们编辑规则配置信息: vim /etc/udev/rule.d/70-pers ...
- 懵了!简单的HTTP调用,时延竟如此大?
最近项目测试遇到个奇怪的现象,在测试环境通过 Apache HTTP Client 调用后端的 HTTP 服务,平均耗时居然接近 39.2ms. 图片来自 Pexels 可能乍一看觉得这不是很正常吗, ...
- 作业——11 分布式并行计算MapReduce
作业的要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3319 1.用自己的话阐明Hadoop平台上HDFS和MapRedu ...
- mark_rabbitMQ
一.1.6 和1.7的区别 二.63跟65好像有点差异 有些jar包问题 三.预取策略 https://blog.csdn.net/hry2015/article/details/79078312 四 ...
- Predicting effects of noncoding variants with deep learning–based sequence model | 基于深度学习的序列模型预测非编码区变异的影响
Predicting effects of noncoding variants with deep learning–based sequence model PDF Interpreting no ...
- 一款阿里开源的 Java 诊断工具
Arthas是什么鬼? Arthas是一款阿里巴巴开源的 Java 线上诊断工具,功能非常强大,可以解决很多线上不方便解决的问题. Arthas诊断使用的是命令行交互模式,支持JDK6+,Linux. ...
- (转)scipy详解
原文:https://www.cnblogs.com/ws0751/p/8361353.html#top 登月图片消噪 scipy.fftpack模块用来计算快速傅里叶变换速度比传统傅里叶变换更快 ...
- WebGL学习笔记(五):变换库
在WebGL开始绘制之前,我们需要通过自己对3D空间进行矩阵和向量的运算,使用网上已经成熟的转换库,可以避免自己去实现这些复杂的数学运算. 我们这里选择的是gl-matrix库,下载地址:https: ...