目录:

  多线程的实现方法:

    继承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基础学习总结 -- 多线程的实现的更多相关文章

  1. Java基础学习(八) - 多线程

    理解线程 进程是指一个内存中运行的应用程序,系统运行一个程序即是一个进程从创建,运行,结束的过程. 线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程. 多线程的特点是并发 ...

  2. Java基础学习篇---------多线程

    一.编写两种多线程的方法 (1).Thread(它是继承Runnable的子类) class MyThread extends Thread{ private int ticket = 5; @Ove ...

  3. Java基础学习笔记总结

    Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...

  4. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  5. Java基础学习-- 继承 的简单总结

    代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...

  6. Java基础学习中一些词语和语句的使用

    在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...

  7. 转载-java基础学习汇总

    共2页: 1 2 下一页  Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3     Java基础学习总结——Java对象的序列化和 ...

  8. java基础学习总结——开篇

    java是我学习的第一门编程语言,当初学习java基础的时候下了不少功夫,趁着这段时间找工作之际,好好整理一下以前学习java基础时记录的笔记,当作是对java基础学习的一个总结吧,将每一个java的 ...

  9. Java基础学习笔记(一)

    Java基础学习笔记(一) Hello World 基础代码学习 代码编写基础结构 class :类,一个类即一个java代码,形成一个class文件,写于每个代码的前端(注意无大写字母) XxxYy ...

随机推荐

  1. Eclipse 常用快捷键 (动画讲解)

    Eclipse有强大的编辑功能, 工欲善其事,必先利其器, 掌握Eclipse快捷键,可以大大提高工作效率.  编辑相关快捷键 注释          Ctrl + / 快速修复    Ctrl + ...

  2. spring定时任务之quartz

    在Spring中,使用JDK的Timer类库来做任务调度功能不是很方便,关键它不可以象cron服务那样可以指定具体年.月.日.时和分的时间.你只能将时间通过换算成微秒后传给它.如任务是每天执行一次,则 ...

  3. 以Excel 作为Data Source,将data导入db

    将Excel作为数据源,将数据导入db,是SSIS的一个简单的应用,下图是示例Excel,数据列是code和name 第一部分,Excel中的数据类型是数值类型 1,使用SSDT创建一个package ...

  4. Evaluate Math Expression

    Evaluate Math Expression eryar@163.com 摘要Abstract:本文简要介绍了数学表达式解析求值的几款开源软件,并结合程序代码说明了OpenCascade中表达式包 ...

  5. jQuery控制tabs打开的数量

  6. 深入学习jQuery鼠标事件

    × 目录 [1]类型 [2]写法 [3]合成事件[4]鼠标按键[5]修改键[6]坐标位置 前面的话 鼠标事件是DOM事件中最常用的事件,jQuery对鼠标事件进行了封装和扩展.本文将详细介绍jQuer ...

  7. PS批处理的使用

    一. 前言 做开发的时候,最多的时候就是图片的使用了.有时候图片的处理都按照同样的步骤,比如说统一将图片的大小调整为固定大小,或者统一在所有的图片的的某个位置上加入文字或者小图片等等,这时候PS的批处 ...

  8. TortoiseGit与github实现项目的上传

    1. 下载并安装相关软件 这里主要涉及的软件包括msysgit和TortoiseGit. msysgit的下载地址:http://msysgit.googlecode.com/files/Git-1. ...

  9. .NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用

    在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下Software Protector序列号生成组件.今天就通过一篇简单的文章来预览一下其强大的功 ...

  10. EntityFramework之孩子删除(四)(你以为你真的懂了?)

    前言 从表面去看待事物视线总有点被层层薄雾笼罩的感觉,当你静下心来思考并让指尖飞梭于键盘之上,终将会拨开浓雾见青天.这是我切身体验. 在EF关系配置中,我暂且将主体对象称作为父亲,而依赖对象称作为孩子 ...