多线程概念

1. 什么是线程呢?

线程是CPU能够进行运算调度的最小单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务,互相之间并不同步。

线程是独立调度和分派的基本单位。线程不拥有系统资源,同一进程中的多条线程将共享该进程中的全部系统资源,但每个线程拥有自己运行必须的数据结构,如虚拟机栈、本地方法栈、程序计数器。由于线程共享进程资源,所以,系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

那么,进程是什么呢?

2. 什么是进程呢?

进程是程序的一次执行过程,是系统运行程序的基本单位,因此,进程是动态的。系统运行一个程序也就是一个进程从创建、运行到消亡的过程。当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程。

线程和进程最大的不同在于:

  • 各个进程是独立的,而线程不一定。
  • 线程执行开销小,但不利于资源的管理和保护。而进程相反。

3. 什么是多线程呢?

多线程,是指从软件或者硬件上实现多个线程并发执行的技术。多线程可以提升系统的整体处理性能。多线程可能会加快程序的运行速度,此外,在一些等待的任务实现上,如用户输入、文件读写和网络收发数据等时,可以释放一些资源(如CPU)。

并发和并行,一样吗?不一样。

  • 并发:在同一时间间隔内,多个任务都在执行。也就是,在这一段时间内,多个任务交替执行。
  • 并行:在同一时刻,多个任务同时执行。

那么,为什么要使用多线程呢?

4. 为什么要使用多线程呢?

  • 从计算机底层来说,线程间的切换和调度,其成本远小于进程。多核CPU也就是说多个线程可以同时运行,从而减少线程上下文切换的开销。
  • 从互联网发展来说,系统的并发量很大,而多线程并发编程是开发高并发系统的基础。多线程机制可以大大提高系统的性能和并发能力

总的来说,多线程可以加快查询运行速度,提剩系统性能和并发能力。

注 —上下文切换:

当前任务使用完CPU分配的时间片时,在切换到另外一个任务之前会先保存自己的状态,以便下次切换到该任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。

5. 怎么创建线程?

线程创建有三种方式:

  1. 继承 Thread 类;
  2. 实现 Runnable 接口;
  3. 实现 Callable 接口。

1)继承 Thread 类

创建线程的三步:

实现过程:

  • 继承 Thread 接口
  • 重写run() 方法
  • 创建目标对象
  • 调用 start()

代码实现

public class MyThread extends Thread {
    // 重写run()方法
    public void run() {
        for (int i=0; i<50; i++) {
            System.out.println("这是子线程"+i);
        }
    }

    public static void main(String[] args) {
        MyThread t = new MyThread();
        // 主线程调用start()方法
        t.start();

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

2)实现 Runnable 接口

创建线程的三步:

实现过程:

  • 实现 Runnable 接口
  • 重写run() 方法
  • 创建目标对象
  • 创建线程对象,通过该线程对象来开启线程。
  • 调用 start()

代码实现

public class MyThread implements Runnable {
    // 重写run()方法
    public void run() {
        for (int i=0; i<50; i++) {
            System.out.println("这是子线程"+i);
        }
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        Thread t = new Thread(thread);
        // 主线程调用start()方法
        t.start();

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

3)实现 Callable 接口

实现过程:

  • 实现 Callable 接口,需要返回值类型
  • 重写 call() 方法,需要抛出异常
  • 创建目标对象
  • 创建执行服务。ExecutorService service = Executors.newFixedThreadPool(1)
  • 提交执行。Future<Boolean> results = ser.submit(t)
  • 获取结果。 boolean res = result.get()
  • 关闭服务。service.shutdownNow()

代码实现

// 实现Callable接口
public class MyThread implements Callable {
    // 重写call()方法
    public void call() {
        for (int i=0; i<50; i++) {
            System.out.println("这是子线程"+i);
        }
    }

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        // 创建执行服务
        ExecutorSerice service = new ExecutorService(nThread:1);
        // 提交执行
        Future<Boolean> result1 = service.submit(t1);
        // 获取结果
        boolean r1 = result1.get();
        // 关闭服务
        service.shutdownNow();
    }
}    

4)run() 和 start() 的区别

执行 run() 的线程:线程执行完之后,主线程才继续执行。

执行 start() 的线程:线程和主线程同时执行。

6. 线程的6个状态有哪些?

线程一般有5个状态:创建、就绪、运行、阻塞、结束。

1)java 中的6个状态

在Java中,线程具有以下6种状态。线程会随着代码的执行在不同的状态间切换。

  • 初始状态。线程被创建,此时还没有调用 start() 方法。
  • 运行状态。包括就绪和运行两种状态。线程创建之后处于初始状态,调用 start() 方法之后,处于可运行状态,在该状态下,线程获得CPU的时间片后就处于运行状态。
  • 等待状态。线程执行 wait() 方法之后,线程进入等待状态。在该状态下,线程需要其他线程的通知才能够回到运行状态。
  • 超时等待状态。超时等待状态相当于在等待状态的基础上加上了超时限制,当超时时间到了后,线程会进入运行状态。通过 sleep(millis)wait(miliis) 可以让线程进入超时等待状态。
  • 阻塞状态。当线程调用同步方法时,如果没有获得锁,线程会进入阻塞状态。
  • 终止状态。当前线程已执行完毕。线程运行完 run() 方法之后,会自然终止,进入终止状态。

2)比较 sleep()wait()

两者都可以暂停线程的执行。

sleep()wait()
是否释放锁(主要的区别)没有释放释放
用途暂停执行线程交互/通信
是否会自动苏醒不会,需要其他线程的通知(调用 notify() )

参考链接:

https://www.bilibili.com/video/BV1V4411p7EF?from=search&seid=11937559633016699466

https://snailclimb.gitee.io/javaguide/#/docs/java/multi-thread/2020%E6%9C%80%E6%96%B0Java%E5%B9%B6%E5%8F%91%E5%9F%BA%E7%A1%80%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93?id=_11-%e4%bd%95%e4%b8%ba%e8%bf%9b%e7%a8%8b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值