Java基础学习总结 -- 多线程的实现
目录:
多线程的实现方法:
继承Thread类
实现Runnable接口
-------------------------------------------------------------------------------------
1. 继承Thread类
继承Thread类之后,需要覆盖父类的 public void run() 方法,作为线程的主方法。
所有线程的执行一定是并发的,即:同一个时间段上会有多个线程交替执行。为了达到这样的目的,绝对不能直接调用run()方法,而是应该调用Thread类的start()方法启动多线程。
调用 start() 方法和调用 run() 方法的对比:
public class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for(int i=0; i<10; i++) {
System.out.println(name + "打印:" + i);
}
}
public static void main(String[] args) {
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
mt1.start();
mt2.start();
mt3.start();
}
}
运行结果:(三个线程同时且交替执行,没有固定的执行顺序)

public class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(name + "打印:" + i);
}
}
public static void main(String[] args) {
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
mt1.run();
mt2.run();
mt3.run();
}
}
运行结果:(三个程序依次顺序执行)

2. start()方法实现多线程的原理
打开Thread类源代码中start()方法的部分:
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
private native void start0();
native关键字是指调用操作系统的方法,start0()方法是所在操作系统的方法。
由于线程的启动需要牵扯到操作系统中资源的分配问题,所以具体的线程的启动应该根据不同的操作系统有不同的实现。而JVM根据不同的操作系统中定义的start0()方法进行不同的实现。这样,在多线程的层次上start0()方法的名称不改变,而不同的操作系统有不同的实现。

原理图
结论:只有Thread类的start()方法才能进行操作系统资源的分配,所以启动多线程的方式永远就是Thread类的start()方法。
3. 实现Runnable接口
一般使用这种方式来实现多线程,因为这样可以避免继承Thread类的单继承局限。
package test;
public class MyThread implements Runnable {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(name + "打印:" + i);
}
}
public static void main(String[] args) {
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
new Thread(mt1).start();
new Thread(mt2).start();
new Thread(mt3).start();
}
}
4. Thread类 与 Runnable接口 的联系与区别
联系:
Thread类是实现了Runnable接口的类。

区别:
Runnable接口实现的多线程要比Thread类实现的多线程更方便的表示出数据共享的概念。
范例:希望有三个线程进行卖票
//使用Thread类实现
public class MyThread extends Thread {
private String name;
int tickets = 5;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
while(tickets>0) {
System.out.println(name + "买票出一张票,剩余票数:" + (--tickets));
}
}
public static void main(String[] args) {
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
mt1.start();
mt2.start();
mt3.start();
}
}
/*
线程C买票出一张票,剩余票数:4
线程A买票出一张票,剩余票数:4
线程B买票出一张票,剩余票数:4
线程A买票出一张票,剩余票数:3
线程C买票出一张票,剩余票数:3
线程A买票出一张票,剩余票数:2
线程B买票出一张票,剩余票数:3
线程A买票出一张票,剩余票数:1
线程C买票出一张票,剩余票数:2
线程C买票出一张票,剩余票数:1
线程A买票出一张票,剩余票数:0
线程B买票出一张票,剩余票数:2
线程B买票出一张票,剩余票数:1
线程B买票出一张票,剩余票数:0
线程C买票出一张票,剩余票数:0
*/
//使用Runnable接口实现
public class MyThread implements Runnable {
int tickets = 5;
@Override
public void run() {
while(tickets>0) {
System.out.println(Thread.currentThread().getName() + "买票出一张票,剩余票数:" + (--tickets));
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
new Thread(mt,"线程A").start();
new Thread(mt,"线程B").start();
new Thread(mt,"线程C").start();
}
}
/*
线程B买票出一张票,剩余票数:3
线程A买票出一张票,剩余票数:4
线程C买票出一张票,剩余票数:2
线程A买票出一张票,剩余票数:0
线程B买票出一张票,剩余票数:1
*/
//同一个线程不能重复启动,否则会出现异常
public class MyThread extends Thread {
int tickets = 5;
@Override
public void run() {
while(tickets>0) {
System.out.println("买票出一张票,剩余票数:" + (--tickets));
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
mt.start();
mt.start();
}
}
/*
Exception in thread "main" 买票出一张票,剩余票数:4
买票出一张票,剩余票数:3
买票出一张票,剩余票数:2
买票出一张票,剩余票数:1
买票出一张票,剩余票数:0
java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at test.MyThread.main(MyThread.java:17)
*/
图释:
使用Thread类的内存情况

使用Runnable接口的内存情况
面试题:请解释多线程的两种实现方式以及区别,并用代码验证?
答:多线程需要一个线程的主类,这个类要么继承Thread类,要么实现Runnable接口;
使用Runnable接口要比Thread类更好地实现数据共享的操作,并且使用Runnable接口可以避免单继承局限。
代码如上。
Java基础学习总结 -- 多线程的实现的更多相关文章
- Java基础学习(八) - 多线程
理解线程 进程是指一个内存中运行的应用程序,系统运行一个程序即是一个进程从创建,运行,结束的过程. 线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程. 多线程的特点是并发 ...
- Java基础学习篇---------多线程
一.编写两种多线程的方法 (1).Thread(它是继承Runnable的子类) class MyThread extends Thread{ private int ticket = 5; @Ove ...
- Java基础学习笔记总结
Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- Java基础学习-- 继承 的简单总结
代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...
- Java基础学习中一些词语和语句的使用
在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...
- 转载-java基础学习汇总
共2页: 1 2 下一页 Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3 Java基础学习总结——Java对象的序列化和 ...
- java基础学习总结——开篇
java是我学习的第一门编程语言,当初学习java基础的时候下了不少功夫,趁着这段时间找工作之际,好好整理一下以前学习java基础时记录的笔记,当作是对java基础学习的一个总结吧,将每一个java的 ...
- Java基础学习笔记(一)
Java基础学习笔记(一) Hello World 基础代码学习 代码编写基础结构 class :类,一个类即一个java代码,形成一个class文件,写于每个代码的前端(注意无大写字母) XxxYy ...
随机推荐
- Eclipse 常用快捷键 (动画讲解)
Eclipse有强大的编辑功能, 工欲善其事,必先利其器, 掌握Eclipse快捷键,可以大大提高工作效率. 编辑相关快捷键 注释 Ctrl + / 快速修复 Ctrl + ...
- spring定时任务之quartz
在Spring中,使用JDK的Timer类库来做任务调度功能不是很方便,关键它不可以象cron服务那样可以指定具体年.月.日.时和分的时间.你只能将时间通过换算成微秒后传给它.如任务是每天执行一次,则 ...
- 以Excel 作为Data Source,将data导入db
将Excel作为数据源,将数据导入db,是SSIS的一个简单的应用,下图是示例Excel,数据列是code和name 第一部分,Excel中的数据类型是数值类型 1,使用SSDT创建一个package ...
- Evaluate Math Expression
Evaluate Math Expression eryar@163.com 摘要Abstract:本文简要介绍了数学表达式解析求值的几款开源软件,并结合程序代码说明了OpenCascade中表达式包 ...
- jQuery控制tabs打开的数量
- 深入学习jQuery鼠标事件
× 目录 [1]类型 [2]写法 [3]合成事件[4]鼠标按键[5]修改键[6]坐标位置 前面的话 鼠标事件是DOM事件中最常用的事件,jQuery对鼠标事件进行了封装和扩展.本文将详细介绍jQuer ...
- PS批处理的使用
一. 前言 做开发的时候,最多的时候就是图片的使用了.有时候图片的处理都按照同样的步骤,比如说统一将图片的大小调整为固定大小,或者统一在所有的图片的的某个位置上加入文字或者小图片等等,这时候PS的批处 ...
- TortoiseGit与github实现项目的上传
1. 下载并安装相关软件 这里主要涉及的软件包括msysgit和TortoiseGit. msysgit的下载地址:http://msysgit.googlecode.com/files/Git-1. ...
- .NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下Software Protector序列号生成组件.今天就通过一篇简单的文章来预览一下其强大的功 ...
- EntityFramework之孩子删除(四)(你以为你真的懂了?)
前言 从表面去看待事物视线总有点被层层薄雾笼罩的感觉,当你静下心来思考并让指尖飞梭于键盘之上,终将会拨开浓雾见青天.这是我切身体验. 在EF关系配置中,我暂且将主体对象称作为父亲,而依赖对象称作为孩子 ...