博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java基础学习总结 -- 多线程的实现
阅读量:4671 次
发布时间:2019-06-09

本文共 5145 字,大约阅读时间需要 17 分钟。

 

目录:

  •   
  •   
  •   
  •   

 

  多线程的实现方法:

    继承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买票出一张票,剩余票数:0java.lang.IllegalThreadStateException    at java.lang.Thread.start(Unknown Source)    at test.MyThread.main(MyThread.java:17)*/

    图释:

   

使用Thread类的内存情况

   

使用Runnable接口的内存情况

  面试题:请解释多线程的两种实现方式以及区别,并用代码验证?

    答:多线程需要一个线程的主类,这个类要么继承Thread类,要么实现Runnable接口;

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

      代码如上。

 

 

 

 

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

你可能感兴趣的文章
添加删除tag
查看>>
ARM学习篇 中断定时理解
查看>>
卷积神经网络在tenserflow的实现
查看>>
[STL]用法
查看>>
PostgresException: 42883: function ifnull(integer, integer) does not exist
查看>>
python3 表情符号编码
查看>>
桥接模式
查看>>
跨server传输数据注意事项
查看>>
使用蒙版--渐变--制作瓶子倒影
查看>>
后代元素 span:first-child{...}
查看>>
LeetCode 540. 有序数组中的单一元素(Single Element in a Sorted Array) 42
查看>>
codevs 5958 无
查看>>
htaccess 实现网址缩短
查看>>
第四周作业&&结对编程
查看>>
12. 构造代码块
查看>>
指针函数与函数指针的区别
查看>>
HDOJ 4734 数位DP
查看>>
我的第一个python web开发框架(15)——公司介绍编辑功能
查看>>
win10
查看>>
JS DOM操作基础
查看>>