一、继承Thread类创建线程类

Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。

Thread类的声明如下:

public class Thread implements Runnable {}

可以看到,Thread本身就实现了Runnable接口。

Java中通过继承Thread类来创建并启动多线程的步骤如下:

01. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

02. 创建Thread子类的实例,即创建了线程对象。

03. 调用线程对象的start()方法来启动该线程。

示例:

package com.demo;

//通过继承Thread类来创建线程类
public class MyThread extends Thread{ private int ticket = 10; //重写run方法
public void run(){
for(int i=0;i<20;i++){
if(this.ticket>0){
System.out.println(this.getName()+" 卖票:ticket"+this.ticket--);
}
}
} public static void main(String[] args) {
// 启动3个线程t1,t2,t3;每个线程各卖10张票!
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();
t2.start();
t3.start();
}
}

运行结果:

Thread-0 卖票:ticket10
Thread-0 卖票:ticket9
Thread-0 卖票:ticket8
Thread-0 卖票:ticket7
Thread-1 卖票:ticket10
Thread-1 卖票:ticket9
Thread-1 卖票:ticket8
Thread-1 卖票:ticket7
Thread-1 卖票:ticket6
Thread-0 卖票:ticket6
Thread-0 卖票:ticket5
Thread-0 卖票:ticket4
Thread-0 卖票:ticket3
Thread-0 卖票:ticket2
Thread-0 卖票:ticket1
Thread-2 卖票:ticket10
Thread-2 卖票:ticket9
Thread-2 卖票:ticket8
Thread-2 卖票:ticket7
Thread-2 卖票:ticket6
Thread-2 卖票:ticket5
Thread-2 卖票:ticket4
Thread-2 卖票:ticket3
Thread-2 卖票:ticket2
Thread-1 卖票:ticket5
Thread-2 卖票:ticket1
Thread-1 卖票:ticket4
Thread-1 卖票:ticket3
Thread-1 卖票:ticket2
Thread-1 卖票:ticket1

结果说明
(01) MyThread继承于Thread,它是自定义个线程。每个MyThread都会卖出10张票。
(02) 主线程main创建并启动3个MyThread子线程。每个子线程都各自卖出了10张票。

二、实现Runnable接口创建线程类

Runnable 是一个接口,该接口中只包含了一个run()方法。它的定义如下:

public interface Runnable {
public abstract void run();
}

实现Runnable接口来创建并启动多线程的步骤如下:

01. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

02. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

03. 调用线程对象的start()方法来启动线程。

需要注意的是:Runnable对象仅仅作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行体。而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法。

示例:

package com.demo;

//通过实现Runnable接口创建多线程
public class MyThread1 implements Runnable{ private int ticket = 10; public void run(){
for(int i=0;i<20;i++){
if(this.ticket>0){
System.out.println(Thread.currentThread().getName()+" 卖票:ticket"+this.ticket--);
}
}
} public static void main(String[] args) {
MyThread1 mt=new MyThread1(); // 启动3个线程t1,t2,t3(它们共用一个Runnable对象),这3个线程一共卖10张票!
Thread t1=new Thread(mt);
Thread t2=new Thread(mt);
Thread t3=new Thread(mt);
t1.start();
t2.start();
t3.start();
} }

运行结果:

Thread-0 卖票:ticket10
Thread-0 卖票:ticket8
Thread-0 卖票:ticket7
Thread-1 卖票:ticket9
Thread-2 卖票:ticket5
Thread-0 卖票:ticket6
Thread-1 卖票:ticket4
Thread-2 卖票:ticket3
Thread-1 卖票:ticket1
Thread-0 卖票:ticket2

结果说明
(01) 和上面“MyThread继承于Thread”不同;这里的MyThread1实现了Thread接口。
(02) 主线程main创建并启动3个子线程,而且这3个子线程都是基于“mt这个Runnable对象”而创建的。运行结果是这3个子线程一共卖出了10张票。这说明它们是共享了MyThread接口的。

三、Thread和Runnable的异同点

Thread 和 Runnable 的相同点:都是“多线程的实现方式”。
Thread 和 Runnable 的不同点:
Thread 是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。我们知道“一个类只能有一个父类,但是却能实现多个接口”,因此Runnable具有更好的扩展性。
此外,Runnable还可以用于“资源的共享”。即,多个线程都是基于某一个Runnable对象建立的,它们会共享Runnable对象上的资源。
通常,建议通过“Runnable”实现多线程!

Java多线程(二)——常用的实现多线程的两种方式的更多相关文章

  1. Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  2. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  3. 多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比

    Thread.Start(),ThreadPool.QueueUserWorkItem都是在实现多线程并行编程时常用的方法.两种方式有何异同点,而又该如何取舍? 写一个Demo,分别用两种方式实现.观 ...

  4. java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))

    Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0)   阅读目录 为什么要克隆? 如何实现克隆 浅克 ...

  5. java的取出map里所有元素的两种方式

    /* * 取出map元素的两种方式 */package com.map.test; import java.util.HashMap;import java.util.Iterator;import ...

  6. 数据结构队列的java实现,包括线性和链式两种方式

    实现的思路为: 采用泛型的方式,首先定义了一个Queue的接口,然后通过实现该接口实现了线性和链式的两种形式的队列: 接口代码如下: package com.peter.java.dsa.interf ...

  7. 二十一 Struts的数据校验两种方式:手动编码和xml校验

    数据的校验: 一.前台校验:JS校验 JS的校验不是必须的,JS可以被绕行,可以提升用户体验 二.后台校验:编码校验 必须的校验 三.校验的方式: 手动编码(不建议使用) 配置文件(支持) 手动编码的 ...

  8. java实现八皇后问题(递归和循环两种方式)

    循环方式: package EightQueens;   public class EightQueensNotRecursive { private static final boolean AVA ...

  9. Java中将xml文件转化为json的两种方式

    原文地址https://blog.csdn.net/a532672728/article/details/76312475 最近有个需求,要将xml转json之后存储在redis中,找来找去发现整体来 ...

  10. Redis实战(二)CentOS 7上Redis两种方式持久化

    Redis的持久化之RDB RDB方式是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据进行快照并且存储到硬盘上. 进行快照的条件在配置文件中指定,有2个参数构成:时间和改动的键的个 ...

随机推荐

  1. IDEA项目搭建十三——服务消费端与生产端通信实现

    一.简介 之前已经完成了EurekaClient的服务生产者和Feign的服务消费者模块的搭建,现在实现统一的通信约定 (1) 统一Request结构 (2) 统一Response结构 (3) 统一E ...

  2. iPhone手机怎么投屏到电脑上

    如今生活水平不断上升,人们更加追求高质量.高享受的生活,所以可以利用一切资源提高生活质量,享受更好的生活体验,比如说手机投屏电脑就可以提高我们的视觉体验,所以更多的人去尝试,那么iPhone手机怎么投 ...

  3. <python3-cookbook>第一章:数据结构和算法

    第一章:数据结构和算法 介绍:python3-cookbook这本书是高级用法,不是小白使用书目的:写作目的是记录下自己学习这本书的过程以及收获书籍地址:https://python3-cookboo ...

  4. git 入门教程之配置 git

    配置 git 安装完成后,还需要最后一步配置就可以愉快使用了,在命令行输入: git config --global user.name "your username" git c ...

  5. Python 魔法方法简介

    1.什么是魔法方法? 魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一 ...

  6. telnet 测试网站是否开启长连接

    测试服务器是否开启keepalive(长连接) telnet 主机名(域名|IP) 80 #发起请求GET /index.html HTTP/1.1Host: www.cbnsc.com 如果请求完后 ...

  7. python爬虫之天气预报网站--查看最近(15天)的天气信息(正则表达式)

    python爬虫之天气预报网站--查看最近(15天)的天气信息(正则表达式) 思路: 1.首先找到一个自己想要查看天气预报的网站,选择自己想查看的地方,查看天气(例:http://www.tianqi ...

  8. python爬虫之12306网站--车站信息查询

    python爬虫查询车站信息 目录: 1.找到要查询的url 2.对信息进行分析 3.对信息进行处理 python爬虫查询全拼相同的车站 目录: 1.找到要查询的url 2.对信息进行分析 3.对信息 ...

  9. Python: 内置私有方法

    ################## __new__ ##################@staticmethod__new__(cls [, ...])类的构造器,创建某个类的实例,返回值应该是c ...

  10. Sublime Text 2 配置PHP调试环境(在windows环境下)

    1:PHP安装,配置环境变量 PHP安装略过- 2:下载Sublime Text 2 下载地址:http://www.sublimetext.com/2 ,选择自己合适的版本 3:点击 sublime ...