一.run()方法和start()方法的区别

在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。

下面看例子:

 package org.thread.demo;

 public class MyThread extends Thread {
private String name;
public MyThread(String name) {
super();
this.name = name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println("线程开始:"+this.name+",i="+i);
}
}
 package org.thread.demo;

 public class ThreadRunDemo {
public static void main(String[] args) {
MyThread mt1=new MyThread("线程a");
MyThread mt2=new MyThread("线程b");
mt1.run();
mt2.run();
}
}

console:

结果是按顺序运行,先第一个对象执行,然后第二个对象执行。

在JDK的文档中可以发现,一旦调用start()方法,则会通过JVM找到run()方法。下面启动start()方法启动线程:

 package org.thread.demo;

 public class ThreadStartDemo {
public static void main(String[] args) {
MyThread mt1=new MyThread("线程a");
MyThread mt2=new MyThread("线程b");
mt1.start();
mt2.start();
}
}

console:

这样程序可以正常完成交互式运行。那么为啥非要使用start();方法启动多线程呢?

在JDK的安装路径下,src.zip是全部的java源程序,通过此代码找到Thread中的start()方法的定义,可以发现此方法中使用了private native void start0();其中native关键字表示可以调用操作系统的底层函数,那么这样的技术成为JNI技术(java Native Interface)

综上,可以得出:

start() 方法的作用是启动一个新线程,新线程会执行相应的run()方法。

而run()方法则只是普通的方法调用,在调用线程中顺序运行而已。 

二.Runnable接口

在实际开发中一个多线程的操作很少使用Thread类,而是通过Runnable接口完成。

public interface Runnable{
public void run();
}

例子:

 package org.runnable.demo;
package org.thread.demo; public class MyThreadImpRunnable implements Runnable { private String name;
public MyThreadImpRunnable(String name) {
this.name = name;
} @Override
public void run() {
for(int i=0;i<100;i++){
System.out.println("线程开始:"+this.name+",i="+i);
}
}
}

但是在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。此时观察Thread类,有一个构造方法:public Thread(Runnable targer)此构造方法接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现的多线程。(start()可以协调系统的资源):

 package org.thread.demo;

 public class RunnableDemo {
public static void main(String[] args) {
MyThreadImpRunnable mt1=new MyThreadImpRunnable("线程a");
MyThreadImpRunnable mt2=new MyThreadImpRunnable("线程b");
new Thread(mt1).start();
new Thread(mt2).start();
}
}

console:

两种实现方式的区别和联系:

在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:

避免点继承的局限,一个类可以继承多个接口;

实现资源的共享

以卖票程序为例,通过Thread类完成:

 package org.thread.demo;

 public class MyTheard02 extends Thread{
private int ticket=10;
public void run(){
for(int i=0;i<20;i++){
if(this.ticket>0){
System.out.println("卖票:ticket"+this.ticket--);
}
}
}
}

下面通过三个线程对象,同时卖票:

 package org.thread.demo;
public class ThreadTicket{
public static void main(String[] args) {
MyThread02 mt1=new MyThread02();
MyThread02 mt2=new MyThread02();
MyThread02 mt3=new MyThread02();
mt1.start();//每个线程都各卖了10张,共卖了30张票
mt2.start();//但实际只有10张票,每个线程都卖自己的票
mt3.start();//没有达到资源共享
}
}

console:

每个线程都各卖了10张,共卖了30张票,但实际只有10张票,每个线程都卖自己的票,没有达到资源共享

如果用Runnable就可以实现资源共享,下面看例子:

 package org.thread.demo;

 public class MyThread02ImpRunnable implements Runnable {
private int ticket=10;
@Override
public void run() {
for(int i=0;i<20;i++){
if(this.ticket>0){
System.out.println("通过实现runnable接口卖票:ticket"+this.ticket--);
}
}
}
 package org.thread.demo;

 public class RunnableTicket {
public static void main(String[] args) { MyThread02ImpRunnable mt=new MyThread02ImpRunnable(); new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一
new Thread(mt).start();//个实例化对象mt,就会出现异常
new Thread(mt).start();
}
}

console:

虽然现在程序中有三个线程,但是一共卖了10张票,也就是说使用Runnable实现多线程可以达到资源共享目的。

多线程之Tread类和Runnable的区别的更多相关文章

  1. Java基础-进程与线程之Thread类详解

    Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...

  2. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  3. 多线程之ThreadLocal类

    深入研究java.lang.ThreadLocal类 0.前言 ThreadLocal(线程变量副本)Synchronized实现内存共享,ThreadLocal为每个线程维护一个本地变量.采用空间换 ...

  4. Java多线程之Callable接口与Runnable的实现以及选择

    通过实现Runnable接口的实现 package Thread; import java.util.concurrent.ExecutorService;import java.util.concu ...

  5. 多线程之Thread类

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...

  6. JUC多线程之ThreadPoolExecutor类任务执行流程

    ThreadPoolExecutor类: ThreadPoolExecutor是我们最常用的一个线程池类,它实现了AbstractExecutorService接口.首先来看一下它的构造器及相关关键变 ...

  7. 多线程之Parallel类

    Parallel类是对线程的一个抽象.该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性. Paraller类定义了数据并行地For和ForEach的静态方法,以及 ...

  8. C# 多线程之Thread类

    使用System.Threading.Thread类可以创建和控制线程. 常用的构造函数有:   // 摘要: // 初始化 System.Threading.Thread 类的新实例,指定允许对象在 ...

  9. 多线程之:lock和synchronized的区别

    多次思考过这个问题,都没有形成理论,今天有时间了,我把他总结出来,希望对大家有所帮助 1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候 ...

随机推荐

  1. python pycharm 注册码

    D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1lIjoiI ...

  2. Vue源码解读-构造函数

    src/core/instance/index.js此文件主要实现了Vue初始化 // 引入模块 import { initMixin } from './init' import { stateMi ...

  3. [转载]Ethernet,Half-Duplex/Full-Duplex,CSMA

    原文地址:Ethernet,Half-Duplex/Full-Duplex,CSMA/CD,Auto-Negotiation作者:心田麦浪 CSMA/CD(Carrier Sense Multiple ...

  4. 安装BCG界面库 会导致vs2013qt库配置消失

    安装BCG界面库 会导致vs2013qt库配置消失 安装BCG界面库 会导致vs2013qt库配置消失 安装BCG界面库 会导致vs2013qt库配置消失

  5. __name__='main' 这句代码是什么意思?《读书笔记》

    当我们阅读 别人的python代码都会有 if name == "main"这么一行语句,但却不知道为什么要写这个?有什么用 想知道这段代码什么意思让我们来根据例子来测试一下 我们 ...

  6. springboot-mybatis配置(xml)/springboot-jpa配置

    #springboot-mybatis配置(xml) spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource. ...

  7. Luogu P3886 [JLOI2009]神秘的生物 最小表示法,轮廓线DP,插头DP,动态规划

    亲手写掉的第一道最小表示法!哈哈哈太开心啦~ 不同于以往的几个插头\(dp\),这个题目的轮廓线是周围的一圈\(n\)个格子.而其所谓"插头"也变成了相邻格子的所属连通分量编号,并 ...

  8. @ResponseStatus注解作用

    @ResponseStatus注解有两种用法,一种是加载自定义异常类上,一种是加在目标方法中 这里我们说一下加在目标方法上的这种情况,注解中有两个参数,value属性设置异常的状态码,reaseon是 ...

  9. 《Python3-标准库》讲解

    一.string:文本常量和模板 函数:capwords()-------------------------------------------------- import string  s = ...

  10. 【NOIP2014模拟10.25A组】画矩形

    题目 分析 由于要求按时间顺序来操作,考虑整体二分: 对于一段二分出来的区间,将左区间的修改和右区间的查询取出来,每次更新每个查询的答案,正确性显然. 现在有一对修改和查询的操作(保证所有的查询都在修 ...