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 ...
随机推荐
- Knockout中文开发指南(完整版API中文文档) 目录索引
a, .tree li > span { padding: 4pt; border-radius: 4px; } .tree li a { color:#46cfb0; text-decorat ...
- WPF根据Oracle数据库的表,生成CS文件小工具
开发小工具的原因: 1.我们公司的开发是客户端用C#,服务端用Java,前后台在通讯交互的时候,会用到Oracle数据库的字段,因为服务器端有公司总经理开发的一个根据Oracle数据库的表生成的cla ...
- 【转】WPF 给DataGridTextColumn统一加上ToolTip
源地址:http://dongguojun.iteye.com/blog/1671963 我发现WPF中DataGridTextColumn直接设置它的ToolTipService.Tooltip并不 ...
- codeforces Round #320 (Div. 2) C. A Problem about Polyline(数学) D. "Or" Game(暴力,数学)
解题思路:就是求数 n 对应的二进制数中有多少个 1 #include <iostream> #include<cstdio> using namespace std; int ...
- scikit-learn 逻辑回归类库使用小结
之前在逻辑回归原理小结这篇文章中,对逻辑回归的原理做了小结.这里接着对scikit-learn中逻辑回归类库的我的使用经验做一个总结.重点讲述调参中要注意的事项. 1. 概述 在scikit-lear ...
- OWIN 中 K Commands 与 OwinHost.exe 相等吗?
OwinHost.exe: While some will want to write a custom process to run Katana Web applications, many wo ...
- 小菜学习Winform(三)Socket点对点通信
前言 Socket的英文原义是“孔”或“插座”,其实在网络编程中Socket就是这个意思,就像我们打电话,要首先知道对方的手机号一样,这个手机号就相当于一个Socket号.一个插座,在网络编程中就是i ...
- 在Excel表里面插入背景图
工作中我们会经常用到MS Excel,通常我们打开MS Excel,里面的工作表都是空白单调的背景.当然了,MS Excel可以在工作簿里面插入背景图片.那么问题来了,如果你没有安装Microsoft ...
- 让 OpenAL 也支持 S16 Planar(辅以 FFmpeg)
正在制作某物品,现在做到音频部分了. 原本要采用 SDL2_mixer 的,不过实验结果表明其失真非常严重,还带有大量的电噪声.不知道是不是我打开的方式不对…… 一气之下去看 OpenAL,结果吃了闭 ...
- POST方式提交表单时,后台接受实体如果继承了父类,将无法映射表单对应数据
引言 刚才在做一个post提交表单时,我在表单里放了几个隐藏域用来存放数据,表单name属性和后台实体属性签名保持一致.只是后台Action参数包含继承关系,所以无法获取到表单对应的值.刚开始一直纳闷 ...