线程基础

Thread 类的每一个实例都表示一个线程, 进程是操作系统级别的多任务,JVM 就是运行在一个进程中的,所以在Java 中我我们只考虑线程

# 线程状态

 

 

 1.new :当我们new 一个线程时,该线程并没有纳入线程调度,而是处于一个new状态。

2.runnable: 当调用线程的start方法后,该线程纳入线程调度的控制,其处于一个可运行状态,等待分配时间片段以并发运行。

3.running:当线程被分配时间片段后其被cpu执行,这是该线程处于running状态。

4.blocked: 当线程在运行过程中可能会出现阻塞现象,比如等待用户输入信息等。但阻塞状态不是百分百出现的,具体要看代码中是否有相关需求。

5.Dead: 当线程的任务全部运行完毕,或在运行过程中抛出了一个未捕获的异常,那么线程结束,等待GC回收

# 创建线程

创建线程有两种方式

方式1:定义一个类并继承Thread,然后重写run方法,在其中书写线程任务逻辑:

Thread t1 = new MyThread1();
Thread t2 = new MyThread2();
t1.start();
t2.start();

class MyThread1 extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("are you ok?");
}
}
}
class MyThread2 extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("of course");
}
}
}


启动线程要调用start方法,不能直接调用run方法。start方法会将当前线程纳入到线程调度中,使其具有并发运行的能力。start方法很快会执行完毕。当start方法执行完毕后,当前线程的run方法会很快的被执行起来(只要获取到了cpu时间片)。但不能理解为调用start方法时run方法就执行了!

线程有几个不可控因素:

  1. cpu分配时间片给哪个线程我们说了不算。

  2. 时间片长短也不可控。

  3. 线程调度会尽可能均匀的将时间片分配给多个线程。

第一种创建线程的方式存在两个不足:

  1. 由于java是单继承的,这就导致我们若继承了Thread类就无法再继承其他类,这在写项目时会遇到很大问题;

  2. 由于我们定义线程的同时重写run方法来定义线程要执行的任务,这就导致线程与任务有一个强耦合关系,线程的重用性变得非常局限。

    方式 2:定义一个类并实现Runnable接口然后在创建线程的同时将任务指定。因为是实现Runnable接口,所以不影响其继承其他类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Thread t1 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
    System.out.println("are you ok?");
    }
    });
    t1.start();

    Thread t2 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
    System.out.println("of course");
    }
    });
    t2.start();
 
posted @ 2023-02-16 13:06  这很周锐  阅读(14)  评论(0编辑  收藏  举报