实现多线程的两种方式

声明

版权声明:本文参考CSDN博主「一个快乐的野指针~」的原创文章,仅用作个人学习,特此声明
原文链接: https://blog.csdn.net/qq_44715943/article/details/116714584

第一种方式

编写一个类,直接 继承 java.lang.Thread,重写 run方法

  1. 怎么创建线程对象? new继承线程的类。
  2. 怎么启动线程呢? 调用线程对象的 start() 方法。

代码

public class ThreadTest {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        // 启动线程
        t.run(); // 不会启动线程,不会分配新的分支栈。(这种方式就是单线程。)
        //t.start();
        //这里的代码还是运行在主线程中。
        for(int i = 0; i < 5; i++){
            System.out.println("主线程--->" + i);
        }
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        // 编写程序,这段程序运行在分支线程中(分支栈)。
        for(int i = 0; i < 10; i++){
            System.out.println("分支线程--->" + i);
        }
    }
}

注意

观察上图发现了一个问题,我已经创建了一个新的分支线程了,为什么还是先走了run方法再走main方法呢?

原来java线程中,run方式和start方式是有区别的


run():在当前线程开启,比如当前线程是主线程,那么运行在主线程,如果当前线程是子线程,那么在子线程运行。还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

start():通过该方法启动线程的同时也创建了一个线程,真正实现了多线程,这是无需等待run()方法中的代码执行完毕就可以直接执行线程外面的代码,通过start创建的线程处于可运行状态,当得到CPU时间片后就会执行其中的run方法, 这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束, 此线程随即终止。

如下图所示,run方法运行结束,此线程随即终止

总结★★★★★

  • t.run() 不会启动线程,只是普通的调用方法而已。不会分配新的分支栈。(这种方式就是单线程。)
  • t.start() 方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了。这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了。线程就启动成功了。启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)
    run方法在分支栈的栈底部,main方法在主栈的栈底部。run和main是平级的。

注意:以下两张图片由原作者基于其原创代码绘制,在此处仅供学习理解

调用run()方法内存图:

调用start()方法内存图:

第二种方式:

编写一个类,实现 java.lang.Runnable 接口,实现run方法

  1. 怎么创建线程对象? new线程类传入可运行的类/接口。
  2. 怎么启动线程呢? 调用线程对象的 start() 方法。

注意:
第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活。

普通方式

/**
 * 实现线程的第二种方式
 */
public class ThreadTest2 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        // 启动线程
        t.start();

        for(int i = 0; i < 100; i++){
            System.out.println("主线程--->" + i);
        }
    }
}

// 这并不是一个线程类,是一个可运行的类。它还不是一个线程。
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
            System.out.println("分支线程--->" + i);
        }
    }
}

采用匿名内部类

/**
 * 实现线程的第二种方式:采用匿名内部类
 */
public class ThreadTest3 {
    public static void main(String[] args) {
        // 创建线程对象,采用匿名内部类方式。
        Thread t = new Thread(new Runnable(){
            @Override
            public void run() {
                for(int i = 0; i < 100; i++){
                    System.out.println("t线程---> " + i);
                }
            }
        });

        // 启动线程
        t.start();

        for(int i = 0; i < 100; i++){
            System.out.println("main线程---> " + i);
        }
    }
}
posted @ 2022-04-18 21:46  无关风月7707  阅读(52)  评论(0编辑  收藏  举报