一个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. 我的Android前生今世之缘-学习经验-安卓入门教程(六)

    关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号 欢迎大家关注我的微信公众号:「醉翁猫咪」 据我所知,网上教学资料一堆一堆的,那么还有很多人说,如何学习? ...

  2. c语言博客作业03--循环结构

    0.展示PTA总分 1.本章学习总结 1.1学习内容总结 循环语句 for语句: for( 表达式1; 表达式2; 表达式3 ) { // 需要执行的语句; } 其执行过程是:表达式 1 首先执行且只 ...

  3. tensorflow学习(一)

    今天开始学习tensorflow框架,从极客学院下载了官方中文教程(15年翻译的),第一天开始学习第一章ng基本流程和原理,作为前奏.然后写了代码,验证一下,准确率确实非常高,非常好用.把代码上传,作 ...

  4. OpenFOAM——平行平板间具有相对运动(库埃特流)

    本算例翻译整理自:http://the-foam-house5.webnode.es/products/chapter-1-plane-parallel-plates-case/ 这个算例研究了一个距 ...

  5. 谈下sublime和vscode

    sublime用了好多年一直没有换掉 它的体积小运行启动快用着一直很顺手,而且也有不少的插件可以去安装, 而相对于vscode 开始觉得他启动慢有点笨重的感觉,可能是我电脑原因用着卡卡的所以一直没换成 ...

  6. #C++初学记录ACM补题(D. Candies!)前缀和运算。

    D - Candies!   Consider a sequence of digits of length [a1,a2,-,a]. We perform the following operati ...

  7. md5加密后不能解密

    MD5加密原理是散列算法,散列算法也称哈希算法.计算机专业学的数据结构就有哈希表这一知识点.比如10除以3余数为一,4除以3余数也为一,但余数为一的就不知道这个数是哪个了.所以md5不能解密.就算是设 ...

  8. 【转】使用AllureReport生成测试报告

    Allure简介 Allure是一个report框架,可以基于一些测试框架生成测试报告,比较常用的一般是Junit/Testng框架:Allure 生成的报告样式简洁美观,同时又支持中文:Allure ...

  9. Cannot find Makefile. Check your build settings.

    QT Cannot find Makefile. Check your build settings. Error while building/deploying project qt_client ...

  10. sudo passwd root:没有相关指令

    在linux里如果想要修改密码,就输入这个指令,但是会出现没找到这个指令,是因为环境变量里没有passwd. 解决:查找passwd的位置,sudo find / -name passwd 然后进入p ...