Java基础之多线程

发布于:2023-01-02 ⋅ 阅读:(551) ⋅ 点赞:(0)

一、并发和并行

  • 并发:指两个或多个事件在同一个时间段内发生。
  • 并行:指两个或多个事件在同一时刻发生(同时发生)。

在这里插入图片描述

二、进程和线程

  • 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位。

  • 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

  • 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

在这里插入图片描述

三、线程调度

  • 分时调度:所有线程轮流使用CPU,平均分配每个线程占用CPU的时间。

  • 抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

四、创建线程

Java17
Thread类地址:java.lang.Thread

There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread.The other way to create a thread is to declare a class that implements the Runnable interface. That class then implements the run method.

4.1 实现方案一:继承Thread类

  1. 定义一个子类 MyThread 继承线程类 java.lang.Thread,重写 run() 方法
  2. 创建 MyThread 类的对象
  3. 调用线程对象的 start() 方法启动线程(启动后还是执行 run 方法的)
package com.wangpeng;

/**
 * 多线程的创建方式一:继承Thread类 重写run方法
 */
public class ThreadDemo {
    public static void main(String[] args) {
        // 1.创建子线程对象
        Thread myThread = new MyThread();
        // 2.调用start方法启动线程
        myThread.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行输出" + i);
        }
    }
}

class MyThread extends Thread{
    /**
     * 重写run方法,里面定义子线程需要做什么。
     */
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

4.2 实现方案二:实现Runnable接口

  1. 定义一个线程任务类 MyRunnable 实现 Runnable 接口,重写 run()方法
  2. 创建 MyRunnable 对象
  3. 把 MyRunnable 任务对象交给 Thread 处理
  4. 调用线程对象的 start() 方法启动线程
package com.wangpeng;

/**
 * 多线程的创建方式二:实现Runnable接口,并重写其run方法
 */
public class DemoThreadTwo {
    public static void main(String[] args) {
        // 1. 创建一个MyRunnable对象
        Runnable myRunnable = new MyRunnable();
        // 2.把MyRunnable对象交给进程处理
        Thread thread = new Thread(myRunnable);
        // 3.启动线程
        thread.start();
        for (int i = 0; i < 8; i++) {
            System.out.println("主线程执行输出:" + i);
        }
    }
}

class MyRunnable implements Runnable{
    // 重写run方法,定义线程执行任务
    @Override
    public void run() {
        for (int i = 0; i < 8; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

五、线程常用方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
获取线程名称及设置线程名称

package com.wangpeng;

public class DemoThreadThree {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + " :" + i);
        }
        Thread t1 = new MyThreadOne();
        t1.setName("线程一");
        t1.start();
        Thread t2 = new MyThreadOne();
        t2.setName("线程二");
        t2.start();

    }
}

class MyThreadOne extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + " :" + i);
        }
    }
}

main :0
main :1
main :2
线程二 :0
线程一 :0
线程二 :1
线程一 :1
线程二 :2
线程一 :2

Thread类的线程休眠方法
在这里插入图片描述

六、线程安全问题

  • 多个线程同时操作同一个共享资源的时候可能出现业务安全问题,称为线程安全问题。

七、线程同步

  • 加锁:把共享资源进行上锁,每次只能一个线程进入,访问完毕后以后解锁,然后其他线程才能进来。

  • 同步代码块

    1. 作用:把出现线程安全问题的核心代码给上锁。
    2. 原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行。
      请添加图片描述
  • 同步方法

    1. 作用:把出现线程安全问题的核心方法给上锁。
    2. 原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行。

在这里插入图片描述

  • 取钱案例

在这里插入图片描述

one来取钱了,吐出100000.0 账户余额还剩0.0
two来取钱了,余额不足!

锁对象的规范要求:

  • 规范上:建议使用共享资源作为锁对象
  • 对于实例方法建议使用this作为锁对象
  • 对于静态方法建议使用字节码(类名.class)对象作为锁对象
本文含有隐藏内容,请 开通VIP 后查看