【多线程】初步认识Thread类及其应用

💐个人主页:初晴~

📚相关专栏:多线程 / javaEE初阶


        上篇文章我们简单介绍了什么是进程与线程,以及他们之间的区别与联系,实际应用中还是以多线程编程为主的,所以这篇文章就让我们更加深入地去剖析多线程编程的具体应用吧

目录

一、初识Thread类

1、创建线程

(1)继承Thread类

(2)实现Runnable接口

(3)匿名内部类

2、多线程的优势-增加运⾏速度

二、 Thread 类及常⻅⽅法

1、 Thread 的常⻅构造⽅法

2、 Thread 的⼏个常⻅属性

三、线程的状态

四、线程的核心操作

1、启动一个线程-start()

2、获取当前线程引用

3、休眠当前线程

4、线程的中断(终止)

5、线程等待-join()

总结


一、初识Thread类

⼀个线程就是⼀个 "执⾏流". 每个线程之间都可以按照顺序执⾏⾃⼰的代码. 多个线程之间 "同时" 执⾏着多份代码.
Java 的线程 和 操作系统线程 的关系
线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对⽤⼾层提供了⼀些 API 供⽤⼾使⽤(例如 Linux 的 pthread 库).

1、创建线程

Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装
接下来我们就来看一下创建线程的几种写法吧:

(1)继承Thread类

编写的MyThread需要继承Thread类,不需要导包,因为Thread类是java.lang中内置的类。

继承不是主要目的,主要是为了重写Thread类中的run方法,在其中写入所创建线程需要执行的逻辑语句

若要让线程运行,需先实例化编写的MyThread类,接着调用start方法就会在进程内部创建一个新的线程,新的线程就会执行刚才run里的代码。

具体代码如下:

class MyThread extends Thread{
    //重写run方法
    @Override
    public void run(){
        //线程执行的逻辑
        System.out.println("Hello World!");
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread myThread=new MyThread();
        //创建线程
        myThread.start();
    }
}

这个代码,运行起来是一个进程,但这个进程包含了两个线程。
1、调用main方法的线程被称为“主线程”,之前提过一个进程中至少有一个线程,这个线程就是主线程
2、调用myThread.start()方法时会手动创建一个新的线程
主线程和新线程会并发/并行地在CPU上运行
不过,上述代码还不能很好地体现多线程编程的并发性与随机性,接下来用一个更加形象的代码表示一下:
class MyThread extends Thread{
    //重写run方法
    @Override
    public void run(){
        while (true){
            System.out.println("Hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread t=new MyThread();
        //创建线程
        t.start();
        while (true){
            System.out.println("Hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

可以发现,多个线程之间,谁先去CPU上调度执行,这个过程是 “不确定的”,这个调度顺序取决于操作系统内核里的 “调度器”,调度器里有一套规则,但是对于应用程序开发,无法进行干预,也无法察觉,因此把这个过程近似于 “随机”,多线程的运行调度也被称之为 “抢占式执行”

注意:

上述代码中,并没有直接手动调用run方法,但是也被执行了。像run这种,用户手动定义了,但是没有手动调用,最终被系统/库/框架调用执行了的方法,被称为“回调函数(call back)”

(2)实现Runnable接口

Runnable就是用来描述“要执行的任务”是什么
class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("Hello Runnable!");
    }
}
public class Main {
    public static void main(String[] args) {
        MyRunnable runnable=new MyRunnable();
        Thread myThread=new Thread(runnable);
        //创建线程
        myThread.start();
    }
}

通过Thread创建线程,而线程要执行的任务是通过Runnable来描述的,而不是通过Tread自己来描述,这样能起到一定的“解耦合”的作用,便于代码后期维护。

Runnable只是描述了一个任务,并不与“线程”强相关,后续执行这个任务的载体可以是线程,也可以是其他东西,比如线程池、虚拟线程(协程)等,一定程度上提高了代码的复用率。

对⽐上⾯两种⽅法:
继承 Thread 类, 直接使⽤ this 就表⽰当前线程对象的引⽤.
实现 Runnable 接⼝, this 表⽰的是 MyRunnable 的引⽤. 需要使⽤Thread.currentThread()

(3)匿名内部类

匿名指没有类名,内部类指定义在其它类内部的类,匿名内部类一般就是“一次性”使用的类,用完就丢掉,相对来说内聚性会更好一些

匿名内部类创建 Thread ⼦类对象
// 使⽤匿名类创建 Thread ⼦类对象
Thread t=new Thread(){
    @Override
    public void run() {
        System.out.println("使⽤匿名类创建 Thread ⼦类对象");
    }
};
这个方法本质上和(1)是一致的,具体原理如下:
1、定义匿名内部类,这个类是Thread的子类
2、类的内部,重写了父类的run方法
3、创建了一个子类的实例,并把实例的引用赋值给了t
匿名内部类创建 Runnable ⼦类对象:
//使⽤匿名类创建 Runnable ⼦类对象
Thread t2=new Thread(new Runnable() {
    @Override
    public void run() {
        System
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值