Java知多少(58)线程Runnable接口和Thread类详解
大多数情况,通过实例化一个Thread对象来创建一个线程。Java定义了两种方式:
- 实现Runnable 接口;
- 可以继承Thread类。
下面的两小节依次介绍了每一种方式。
实现Runnable接口
创建线程的最简单的方法就是创建一个实现Runnable 接口的类。Runnable抽象了一个执行代码单元。你可以通过实现Runnable接口的方法创建每一个对象的线程。为实现Runnable 接口,一个类仅需实现一个run()的简单方法,该方法声明如下:
public void run( )
在run()中可以定义代码来构建新的线程。理解下面内容是至关重要的:run()方法能够像主线程那样调用其他方法,引用其他类,声明变量。仅有的不同是run()在程序中确立另一个并发的线程执行入口。当run()返回时,该线程结束。
在你已经创建了实现Runnable接口的类以后,你要在类内部实例化一个Thread类的对象。Thread 类定义了好几种构造函数。我们会用到的如下:
Thread(Runnable threadOb, String threadName)
该构造函数中,threadOb是一个实现Runnable接口类的实例。这定义了线程执行的起点。新线程的名称由threadName定义。
建立新的线程后,它并不运行直到调用了它的start()方法,该方法在Thread 类中定义。本质上,start() 执行的是一个对run()的调用。 Start()方法声明如下:
void start( )
下面的例子是创建一个新的线程并启动它运行:
// Create a second thread.
class NewThread implements Runnable {
Thread t;
NewThread() {
// Create a new, second thread
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
} // This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
} class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
在NewThread 构造函数中,新的Thread对象由下面的语句创建::
t = new Thread(this, "Demo Thread");
通过前面的语句this 表明在this对象中你想要新的线程调用run()方法。然后,start() 被调用,以run()方法为开始启动了线程的执行。这使子线程for 循环开始执行。调用start()之后,NewThread 的构造函数返回到main()。当主线程被恢复,它到达for 循环。两个线程继续运行,共享CPU,直到它们的循环结束。该程序的输出如下:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
如前面提到的,在多线程程序中,通常主线程必须是结束运行的最后一个线程。实际上,一些老的JVM,如果主线程先于子线程结束,Java的运行时间系统就可能“挂起”。前述程序保证了主线程最后结束,因为主线程沉睡周期1000毫秒,而子线程仅为500毫秒。这就使子线程在主线程结束之前先结束。简而言之,你将看到等待线程结束的更好途径。
扩展Thread
创建线程的另一个途径是创建一个新类来扩展Thread类,然后创建该类的实例。当一个类继承Thread时,它必须重载run()方法,这个run()方法是新线程的入口。它也必须调用start()方法去启动新线程执行。下面用扩展thread类重写前面的程序:
// Create a second thread by extending Thread
class NewThread extends Thread {
NewThread() {
// Create a new, second thread
super("Demo Thread");
System.out.println("Child thread: " + this);
start(); // Start the thread
} // This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
} class ExtendThread {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
该程序生成和前述版本相同的输出。子线程是由实例化NewThread对象生成的,该对象从Thread类派生。注意NewThread 中super()的调用。该方法调用了下列形式的Thread构造函数:
public Thread(String threadName)
这里,threadName指定线程名称。
选择合适方法
到这里,你一定会奇怪为什么Java有两种创建子线程的方法,哪一种更好呢。所有的问题都归于一点。Thread类定义了多种方法可以被派生类重载。对于所有的方法,惟一的必须被重载的是run()方法。这当然是实现Runnable接口所需的同样的方法。很多Java程序员认为类仅在它们被加强或修改时应该被扩展。因此,如果你不重载Thread的其他方法时,最好只实现Runnable 接口。这当然由你决定。然而,在本章的其他部分,我们应用实现runnable接口的类来创建线程。
Java知多少(58)线程Runnable接口和Thread类详解的更多相关文章
- Java基础-多线程编程-1.随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。
1.随便选择两个城市作为预选旅游目标.实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市.分别用Runnable接口和Thread ...
- Java基础-进程与线程之Thread类详解
Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...
- java.lang.Thread类详解
java.lang.Thread类详解 一.前言 位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前 ...
- “全栈2019”Java第六十七章:内部类、嵌套类详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- java中多线程中Runnable接口和Thread类介绍
java中的线程时通过调用操作系统底层的线程来实现线程的功能的. 先看如下代码,并写出输出结果. // 请问输出结果是什么? public static void main(String[] args ...
- 实验六 多线程编程 1.随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。
//继承Thread类 package zuoye; //继承Thread类 public class City extends Thread{ private String name; public ...
- 随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。
public class Testlvyou extends Thread{ @Override public void run() { test(); } private void test() { ...
- 【Python】Java程序员学习Python(七)— 文本类详解(字符串、str)
如果一个女孩子喜欢看龙猫,那么请珍惜她,呵护她 任何一门语言,字符串总是最基本也是最需要掌握的一个变量,想想入门的Hello World,输出的就是字符串. 官方文档:https://docs.pyt ...
- Java线程创建形式 Thread构造详解 多线程中篇(五)
Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...
随机推荐
- 最小生成树之克鲁斯卡尔(kruskal)算法
#include <iostream> #include <string> using namespace std; typedef struct MGraph{ string ...
- 我的 Sublime Text 2 笔记
作为aptana死忠粉的我,最近由于工作需要最近开始使用sublime,初次使用,就被其秒开的启动速度,简洁的界面设计,无干扰的信息提示所这幅. 俗话说,工欲善其事必先利其器,作为码农,在开始编码之前 ...
- 报错:[__NSArrayI objectAtIndex:]: index 5 beyond bounds [0 .. 4]'
报错内容:如下 分析: 遇到这种情况,说明超出了数组的范围 如要插入某组数据,但是这组数据只有10条:但是这里设置为20条.当第11个cell填充数据时就会报错, [__NSArrayI object ...
- pt-query-digest简介使用
简介 pt-query-digest 是用于分析mysql慢查询的一个工具,与mysqldumpshow工具相比,py-query_digest 工具的分析结果更具体,更完善. 有时因为 ...
- Hessian学习总结(二)——使用hessian上传文件
hessian较早版本通过 byte[] 进行文件传输:4.0之后支持 InputStream 作为参数或返回值进行传输. 注意:hessian会读取整个文件,如果文件过大,会导致JVM内存溢出.可以 ...
- boolean和Boolean, char和Character , byte和Byte, short和Short, int和Integer , long和Long , float和Float, double和Double的区别 , String和StringBuffer的区别
Java提供两种不同的类型:引用类型和原始类型(内置类型).Int是java的原始数据类型,Integer是java为int提供的封装类. Java为每个原始数据类型提供了封装类. 其中原始数据类型封 ...
- Visio画流程图风格设置
第一步:选取设计下选用“简单” 第二步:设置颜色为“铅笔” 第三步:设置效果为“辐射” 第四步:效果
- HOW TO REPLACE ALL OCCURRENCES OF A CHARACTER IN A STD::STRING
From: http://www.martinbroadhurst.com/replacing-all-occurrences-of-a-character-in-a-stdstring.html T ...
- 把tree结构数据转换easyui的columns
很多时候我们的datagrid需要动态的列显示,那么这个时候我们后台一般提供最直观的数据格式tree结构.那么需要我们前端自己根据这个tree结构转换成easyui的datagrid的columns. ...
- mysqld_safe 无法启动的原因
[root@localhost ~]# 170408 09:53:13 mysqld_safe Logging to '/usr/local/mysql/data/localhost.localdom ...