热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java基础学习总结多线程的实现

目录:继承Thread类start()方法实现多线程的原理实现Runnable接口Thread类与Runnable接口的联系与区别多线程的实现方法

 

目录:

  •   继承Thread类
  •   start()方法实现多线程的原理
  •   实现Runnable接口
  •   Thread类 与 Runnable接口 的联系与区别

 

  多线程的实现方法:

    继承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 &#61; name;}&#64;Overridepublic void run() {for(int i&#61;0; i<10; i&#43;&#43;) {System.out.println(name &#43; "打印&#xff1a;" &#43; i);}}public static void main(String[] args) {MyThread mt1 &#61; new MyThread("线程A");MyThread mt2 &#61; new MyThread("线程B");MyThread mt3 &#61; new MyThread("线程C");mt1.start();mt2.start();mt3.start();}
}

  运行结果&#xff1a;&#xff08;三个线程同时且交替执行&#xff0c;没有固定的执行顺序&#xff09;

   

public class MyThread extends Thread {private String name;public MyThread(String name) {this.name &#61; name;}&#64;Overridepublic void run() {for(int i&#61;0; i<5; i&#43;&#43;) {System.out.println(name &#43; "打印&#xff1a;" &#43; i);}}public static void main(String[] args) {MyThread mt1 &#61; new MyThread("线程A");MyThread mt2 &#61; new MyThread("线程B");MyThread mt3 &#61; new MyThread("线程C");mt1.run();mt2.run();mt3.run();}
}

  运行结果&#xff1a;&#xff08;三个程序依次顺序执行&#xff09;

   

 

  2. start()方法实现多线程的原理

    打开Thread类源代码中start()方法的部分&#xff1a;

public synchronized void start() {if (threadStatus !&#61; 0)throw new IllegalThreadStateException();group.add(this);boolean started &#61; false;try {start0();started &#61; true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {}}
}
private native void start0();

    native关键字是指调用操作系统的方法&#xff0c;start0()方法是所在操作系统的方法。

    由于线程的启动需要牵扯到操作系统中资源的分配问题&#xff0c;所以具体的线程的启动应该根据不同的操作系统有不同的实现。而JVM根据不同的操作系统中定义的start0()方法进行不同的实现。这样&#xff0c;在多线程的层次上start0()方法的名称不改变&#xff0c;而不同的操作系统有不同的实现。

原理图

    结论&#xff1a;只有Thread类的start()方法才能进行操作系统资源的分配&#xff0c;所以启动多线程的方式永远就是Thread类的start()方法。

 

  3. 实现Runnable接口

    一般使用这种方式来实现多线程&#xff0c;因为这样可以避免继承Thread类的单继承局限

package test;public class MyThread implements Runnable {private String name;public MyThread(String name) {this.name &#61; name;}&#64;Overridepublic void run() {for(int i&#61;0; i<5; i&#43;&#43;) {System.out.println(name &#43; "打印&#xff1a;" &#43; i);}}public static void main(String[] args) {MyThread mt1 &#61; new MyThread("线程A");MyThread mt2 &#61; new MyThread("线程B");MyThread mt3 &#61; new MyThread("线程C");new Thread(mt1).start();new Thread(mt2).start();new Thread(mt3).start();}
}

 

  4. Thread类 与 Runnable接口 的联系与区别

    联系&#xff1a;

      Thread类是实现了Runnable接口的类。

      

    区别&#xff1a;

      Runnable接口实现的多线程要比Thread类实现的多线程更方便的表示出数据共享的概念。

      范例&#xff1a;希望有三个线程进行卖票

//使用Thread类实现public class MyThread extends Thread {private String name;int tickets &#61; 5;public MyThread(String name) {this.name &#61; name;}&#64;Overridepublic void run() {while(tickets>0) {System.out.println(name &#43; "买票出一张票&#xff0c;剩余票数&#xff1a;" &#43; (--tickets));}}public static void main(String[] args) {MyThread mt1 &#61; new MyThread("线程A");MyThread mt2 &#61; new MyThread("线程B");MyThread mt3 &#61; new MyThread("线程C");mt1.start();mt2.start();mt3.start();}
}
/*
线程C买票出一张票&#xff0c;剩余票数&#xff1a;4
线程A买票出一张票&#xff0c;剩余票数&#xff1a;4
线程B买票出一张票&#xff0c;剩余票数&#xff1a;4
线程A买票出一张票&#xff0c;剩余票数&#xff1a;3
线程C买票出一张票&#xff0c;剩余票数&#xff1a;3
线程A买票出一张票&#xff0c;剩余票数&#xff1a;2
线程B买票出一张票&#xff0c;剩余票数&#xff1a;3
线程A买票出一张票&#xff0c;剩余票数&#xff1a;1
线程C买票出一张票&#xff0c;剩余票数&#xff1a;2
线程C买票出一张票&#xff0c;剩余票数&#xff1a;1
线程A买票出一张票&#xff0c;剩余票数&#xff1a;0
线程B买票出一张票&#xff0c;剩余票数&#xff1a;2
线程B买票出一张票&#xff0c;剩余票数&#xff1a;1
线程B买票出一张票&#xff0c;剩余票数&#xff1a;0
线程C买票出一张票&#xff0c;剩余票数&#xff1a;0
*/

//使用Runnable接口实现public class MyThread implements Runnable {int tickets &#61; 5;&#64;Overridepublic void run() {while(tickets>0) {System.out.println(Thread.currentThread().getName() &#43; "买票出一张票&#xff0c;剩余票数&#xff1a;" &#43; (--tickets));}}public static void main(String[] args) {MyThread mt &#61; new MyThread();new Thread(mt,"线程A").start();new Thread(mt,"线程B").start();new Thread(mt,"线程C").start();}
}
/*
线程B买票出一张票&#xff0c;剩余票数&#xff1a;3
线程A买票出一张票&#xff0c;剩余票数&#xff1a;4
线程C买票出一张票&#xff0c;剩余票数&#xff1a;2
线程A买票出一张票&#xff0c;剩余票数&#xff1a;0
线程B买票出一张票&#xff0c;剩余票数&#xff1a;1
*/

//同一个线程不能重复启动&#xff0c;否则会出现异常public class MyThread extends Thread {int tickets &#61; 5;&#64;Overridepublic void run() {while(tickets>0) {System.out.println("买票出一张票&#xff0c;剩余票数&#xff1a;" &#43; (--tickets));}}public static void main(String[] args) {MyThread mt &#61; new MyThread();mt.start();mt.start();mt.start();}
}
/*
Exception in thread "main" 买票出一张票&#xff0c;剩余票数&#xff1a;4
买票出一张票&#xff0c;剩余票数&#xff1a;3
买票出一张票&#xff0c;剩余票数&#xff1a;2
买票出一张票&#xff0c;剩余票数&#xff1a;1
买票出一张票&#xff0c;剩余票数&#xff1a;0
java.lang.IllegalThreadStateExceptionat java.lang.Thread.start(Unknown Source)at test.MyThread.main(MyThread.java:17)
*/

    图释&#xff1a;

   

使用Thread类的内存情况

   

使用Runnable接口的内存情况

  面试题&#xff1a;请解释多线程的两种实现方式以及区别&#xff0c;并用代码验证&#xff1f;

    答&#xff1a;多线程需要一个线程的主类&#xff0c;这个类要么继承Thread类&#xff0c;要么实现Runnable接口&#xff1b;

      使用Runnable接口要比Thread类更好地实现数据共享的操作&#xff0c;并且使用Runnable接口可以避免单继承局限。

      代码如上。

 

 

 

 

转:https://www.cnblogs.com/xingyazhao/p/6083638.html



推荐阅读
author-avatar
王丽丽2502934407
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有