一个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{
 private int x = 0;
 public void run(){
  System.out.println(++x);
 }
}
public class Test {
 public static void main(String[] args) throws Exception{
  for(int i=0;i<10;i++){
    Thread t = new MyThread();
    t.start();
  }
  Thread.sleep(10000);//让上面的线程运行完成
  R r = new R();
  for(int i=0;i<10;i++){
    Thread t = new Thread(r);
    t.start();
  }
 }  
}

  上面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的更多相关文章

  1. extends Thread 与 implements Runnable 的区别

    http://blog.csdn.net/zhikun518/article/details/7526298 1.通过实现Runnable接口创建线程 (1).定义一个类实现Runnable接口,重写 ...

  2. Java 中的“implements Runnable” 和“extends Thread”(转)

    知识点 “implements Runnable” 和“extends Thread”的不同 具体分析 最近在学习Android中的Handler消息传递机制时,创建新线程有两种方式:一种是实现Run ...

  3. Java 中的“implements Runnable” 和“extends Thread”

    知识点 “implements Runnable” 和“extends Thread”的不同 具体分析 最近在学习Android中的Handler消息传递机制时,创建新线程有两种方式:一种是实现Run ...

  4. java 多线程 继承Thread和实现Runnable的区别

    1)继承Thread: public class ThreadTest extends Thread { private int count; private String name; public ...

  5. 线程的实现方法以及区别 extends Thread、implements Runable

    /** 线程存在于进程当中,进程由系统创建. 创建新的执行线程有两种方法 注意:   线程复写run方法,然后用start()方法调用,其实就是调用的run()方法,只是如果直接启动run()方法, ...

  6. Thread类和Runnable接口实现多线程--2019-4-18

    1.通过Thread实现 public class TestThread extends Thread{ public TestThread(String name) { super(name); } ...

  7. java中的线程问题(三)——继承Thread VS 实现Runnable的区别

    从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口,如果一定要说它们有什么区别, ...

  8. 探Java多线程Thread类和Runnable接口之间的联系

    首先复习一下Java多线程实现机制,Java实现多线程方法有如下这么几种: 1.继承了(extends)Thread类 2.实现了(implements)Runnable接口 也就是说  有如下两种情 ...

  9. Java 多线程之 Thread 类 和 Runnable 接口初步使用

    目录 Thread 类 Thread之定义线程类 Thread之开启线程 Runnable 接口 Runnable 之定义线程类 Runnable 之开启线程 @ Thread 类 Thread 类是 ...

随机推荐

  1. 基于Linux(中标麒麟)上QT的环境搭建——解决cannot find lGL的问题

    接上一篇,QT在中标麒麟环境安装完成后遇到运行报错的问题 一.问题描述: 在中标麒麟上配置好QT的环境后,新建一个工程,不做其他的任何操作,直接运行都会报cannot find lGL的错误.如图所示 ...

  2. 「2019-8-11提高模拟赛」女装盛宴 (flag)

    传送门 Solution  基环树+倍增+双指针 第一次因为#define int long long而玄学RE 为什么标程都不用开\(long long\)啊 Code  /*玄学RE 看来defi ...

  3. solr(一) 单节点安装部署

    一.solr简介 1.什么是solr? Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件 ...

  4. 在js中添加HTML类样式

    有时候需要给元素添加类样式,但又要保留之前的类,可以使用element.classList.add("类名");

  5. (转载)OpenStack client 调用分析

    https://blog.csdn.net/yenai2008/article/details/72722038?utm_source=itdadao&utm_medium=referral# ...

  6. 《The Boost C++ Libraries》 第一章 智能指针

    Boost.SmartPointers中提供了多种智能指针,它们采用在智能指针析构时释放内存的方式,帮助管理动态分配的对象.由于析构函数在智能指针生命周期结束时被执行,所以由它管理的动态分配对象可以保 ...

  7. Cesium的Property机制总结[转]

    https://www.jianshu.com/p/f0b47997224c 前言 Cesium官方教程中有一篇叫<空间数据可视化>(Visualizing Spatial Data).该 ...

  8. PG11开启WAL归档

    -创建归档目录 mkdir -p $PGDATA/archive_wals chown -R postgres.postgres $PGDATA/archive_wals -修改参数(在配置文件中配置 ...

  9. 强化学习——如何提升样本效率 ( DeepMind 综述深度强化学习:智能体和人类相似度竟然如此高!)

    强化学习     如何提升样本效率 参考文章: https://news.html5.qq.com/article?ch=901201&tabId=0&tagId=0&docI ...

  10. 【原创】MongoDB安装配置详解(标注两个坑)

    1.下载安装 3.4正式版([坑]不要最新版,有可能进度卡在这个位置不动,等了半个小时也没什么反映,) http://downloads.mongodb.org/win32/mongodb-win32 ...