一、Java有两种方式实现多线程,第一个是继承Thread类,第二个是实现Runnable接口。他们之间的联系:

    1、Thread类实现了Runable接口。

  2、都需要重写里面Run方法。

二、实现Runnable接口相对于继承Thread类来说,有如下显著的好处:

  1、适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。

  2、可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。

  3、有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。

看一下以继承Thread的卖票例子:

class MyThread extends Thread{
private int ticket = 5;
public void run(){
while(true){
System.out.println("Thread ticket = " + ticket--);
if(ticket < 0){
break;
}
}
}
}
public static void main(String[] args) {
new MyThread().start();
new MyThread().start(); }

  输出结果:

Thread ticket = 5
Thread ticket = 5
Thread ticket = 4
Thread ticket = 4
Thread ticket = 3
Thread ticket = 2
Thread ticket = 3
Thread ticket = 1
Thread ticket = 2
Thread ticket = 0
Thread ticket = 1
Thread ticket = 0

 从结果可以看出:创建了两个多线程对象,他们分别实现了买票任务; 

实现Runnable接口的卖票例子:

class MyThread2 implements Runnable{
private int ticket = 5;
public void run(){
while(true){
System.out.println("Runnable ticket = " + ticket--);
if(ticket < 0){
break;
}
}
}
} <pre name="code" class="html">public static void main(String[] args) {
MyThread2 m=new MyThread2();
  new Thread(m).start();
  new Thread(m).start(); }

输出结果:

 Runnable ticket = 5
Runnable ticket = 4
Runnable ticket = 3
Runnable ticket = 2
Runnable ticket = 1
Runnable ticket = 0

从结果可以看出虽然我们声明了两个线程,但是一共卖了6张票。他们实现了资源共享。PS:在实际开发中,一定要注意命名规范,其次上面实现Runable接口的例子由于同时操作一个资源,会出现线程不安全的情况,如果情况需要,我们需要进行同步操作。

三、线程多次调用start方法,引发的异常  

  通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止,而CPU再运行其它线程,而如果直接用Run方法,这只是调用一个方法而已,程序中依然只有主线程--这一个线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。

  一个线程对象只能调用一次start方法.从new到等待运行是单行道,所以如果你对一个已经启动的线程对象再调用一次start方法的话,会产生:IllegalThreadStateException异常.

  可以被重复调用的是run()方法。
  Thread类中run()和start()方法的区别如下:
    run()方法:在本线程内调用该Runnable对象的run()方法,可以重复多次调用;
    start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;

Thread和Runnable的区别和联系、多次start一个线程会怎么样的更多相关文章

  1. Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别

    一. java中实现线程的方式有Thread和Runnable Thread: public class Thread1 extends Thread{ @Override public void r ...

  2. 三、多线程之Thread与Runnable的区别

    Thread与Runnable的区别(用三个窗口同时出售10张车票为例子) 运行代码 运行结果 分析 System.out.println("开始测试多线程");class MyT ...

  3. Java学习从菜鸟变大鸟之三 多线程中Thread 和Runnable的区别与运用

    多线程机制是java中的一个特点,掌握它对后面的知识的理解至关重要,是java工程师的必备知识,多线程指在单个程序中可以运行多个不同的线程执行的不同的任务,线程是一个程序内部的顺序控制流.进程是静态的 ...

  4. 并发编程之多线程基础-Thread和Runnable的区别及联系(二)

    上篇文章讲述了创建线程的常用方式 本篇主要分析一下Thread和Runnable两种方式创建线程的区别及联系 联系: ▶Thread类实现了Runable接口. ▶都需要重写里面Run方法. 区别: ...

  5. Thread和Runnable的区别和匿名内部类方式实现线程的创建

    如果一个类继承Thread,则不适合资源共享.但是如果实现了Runable接口的话,则很容易的实现资源共享. 总结:实现Runnable接口比继承Thread类所具有的优势: 1.适合多个相同的程序代 ...

  6. Thread 和 Runnable 的区别

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

  7. java线程(上)Thread和Runnable的区别

    首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈 ...

  8. Java并发实现一(并发的实现之Thread和Runnable的区别)

    package com.subject01; public class ThreadOrRunnable { public static void main(String[] args) { Syst ...

  9. Thread和Runnable的区别

    Runnable源码 Thread源码 结论 Thread实现了Runnable接口的类,使得run支持多线程. 因类的单一继承原则,推荐使用Runnable接口实现多线程

随机推荐

  1. 【原创】STM32工程新建步骤

    1. 新建文件夹          DOC文件夹:        可以存放readme.txt等项目文档     Library文件夹:    可以存放ST库源码,直接复制ST库的源代码到Librar ...

  2. Integer判等的陷阱:你知道Integer内部高速缓冲区IntegerCache吗?

    https://blog.csdn.net/magician_Code/article/details/51469101 我们先来看看下面代码的运行情况: public static void mai ...

  3. 浅谈JavaScript之事件(上)

    一  简述JavaScript及其在浏览器中的地位 (一)  浏览器主要构成 虽然不同浏览器之间存在差异(如Google Chrome,Firefox,Safari和IE等),但单从浏览器构成来说,大 ...

  4. #19 re&jieba模块

    前言 在Python中,需要对字符串进行大量的操作,有时需要从一个字符串中提取到特定的信息,用切片肯定是不行的,所有这一节记录两个强大的文本处理模块,一个是正则表达式re模块,另一个是中文处理模块ji ...

  5. MySQL中间件之ProxySQL(15):ProxySQL代理MySQL组复制

    返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.ProxySQL+组复制前言 在以前的ProxySQL版本中,要支 ...

  6. Perl的浅拷贝和深度拷贝

    首先是深.浅拷贝的概念: 浅拷贝:shallow copy,只拷贝第一层的数据.Perl中赋值操作就是浅拷贝 深拷贝:deep copy,递归拷贝所有层次的数据,Perl中Clone模块的clone方 ...

  7. Python面向对象基础:编码细节和注意事项

    在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节. 例子的模型是父类Em ...

  8. 翻译:replace into语句(已提交到MariaDB官方手册)

    本文为mariadb官方手册:REPLACE INTO的译文. 原文:https://mariadb.com/kb/en/replace/ 我提交到MariaDB官方手册的译文:https://mar ...

  9. [转]使用jenkins实现持续集成

    本文转自:https://www.cnblogs.com/zishengY/p/7170656.html 一.jenkins 介绍 它是一个自动化的周期性的集成测试过程,从检出代码.编译构建.运行测试 ...

  10. CheckForIllegalCrossThreadCalls = false 是干嘛的?

    public Form1() {     InitializeComponent();     CheckForIllegalCrossThreadCalls = false; }       在多线 ...