当前位置 : 主页 > 编程语言 > java >

Java-多线程

来源:互联网 收集:自由互联 发布时间:2022-07-04
一,多线程的概念 进程:正在运行的程序 线程:是进程中的一个执行单元(一条执行路径),一个进程中至少包含一个线程。如果一个进程中有多个线程,这样的程序就称为多线程程

一,多线程的概念

进程:正在运行的程序

线程:是进程中的一个执行单元(一条执行路径),一个进程中至少包含一个线程。如果一个进程中有多个线程,这样的程序就称为多线程程序。

线程的调度:

  • 分时调度:所有线程轮流使用CPU,每个线程平均占用CPU的时间
  • 抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么随机选择一个线程为其分配CPU的资源(随机性),Java 多线程的执行方式就是抢占式的。
  • 注:

  • Java 程序在没有开辟新线程的情况下也会有两个线程:主函数所在的主线程、垃圾回收线程

  • 二,创建线程

    方式一:继承 Thread 类

  • 自定义类继承 Thread 类
  • 重写 run() 方法,在 run() 中明确线程执行的功能
  • 创建 Thread 的子类对象
  • 使用这个子类对象调用 start() 方法开启线程,JVM 会自动调用重写后的 run() 方法
  • public class Test1 {
    public static void main(String[] args) {
    MyThread mt = new MyThread();
    mt.start();
    MyThread mt2 = new MyThread();
    mt2.start();

    for(int i = 1;i <= 100;i++){
    System.out.println("main方法:"+i);
    }
    }
    }
    class MyThread extends Thread{
    // 重写run()方法是为了明确线程中所执行的任务
    @Override
    public void run() {
    for(int i = 1;i <= 100;i++){
    System.out.println(Thread.currentThread().getName()+"---"+i);
    }
    }
    }

    方式二:实现 Runnable 接口

  • 自定义类实现 Runnable 接口
  • 重写 run() 方法,在 run() 中明确线程执行的功能
  • 创建 Runnable 实现类的对象
  • public class Test2 {
    public static void main(String[] args) {
    MyRunnable mr = new MyRunnable();
    Thread t = new Thread(mr);
    t.start();
    Thread t2 = new Thread(mr);
    t2.start();
    for(int i = 1;i <= 300;i++){
    System.out.println("main方法:"+i);
    }
    }
    }
    class MyRunnable implements Runnable{
    @Override
    public void run() {
    for(int i = 1;i<=300;i++){
    System.out.println(Thread.currentThread()+"--"+i);
    }
    }
    }

    继承 Thread 类 和 实现 Runnable 接口的选用:

    使用实现的方式,因为避免了单继承的局限性

    注:同一个线程对象不能重复开启,重复开启会发生 IllegalThreadStateException

    使用匿名内部类的方式创建线程并开启:

    new Thread(){
    public void run(){
    // 线程执行的任务
    }
    }.start();new Thread(new Runnable(){
    public void run(){
    // 线程执行的任务
    }
    }).start();



    三,线程中的方法

  • String getName():返回线程的名称
  • static Thread currentThread():返回线程对象,
    Thread [ Thread - 0 , 5 , main]
  • Thread - 0:线程的名称
  • 5:优先级
  • main:在主函数中开启的
  • static void sleep(long time)

  • 四,线程安全问题

    什么是线程安全:如果有多个线程同时执行,这些线程同时操作同一个内容,程序运行后的结果和单线程运行的结果是一样的时候,就称为线程安全。

    完成 3 个窗口同时卖票案例时,发现了重复票和负数票的情况,原因是多个线程在操作同一个 ticket 变量,

    在某个线程通过了 if 判断后,被其他线程抢夺了 CPU 的执行权,所以 if 后的 ticket-- 操作,在一次判断后重复执行了多次。

    解决方式:

  • 同步代码块
    格式:
  • synchronized(锁对象){
    // 可能发生线程安全问题的代码
    }

    注:

  • 同步代码块中的锁对象可以是任意的
  • 必须保证多个线程使用的锁对象是同一个
  • 锁对象的作用:将同步代码块锁定,同一时间只允许让一个线程进入同步代码块
  • 同步函数
    步骤:
  • 将可能发生线程安全问题的代码抽取到一个方法中
  • 再在这个方法上添加 synchronized 修饰符
  • 格式:

    public synchronized 返回类型 方法名(参数){
    // 可能发生线程安全问题的代码
    }

    注:

  • 同步函数中有锁吗?有,同步函数中的锁是 this
  • 在使用继承 Thread 的方式去创建线程时,使用同步函数不能保证线程同步,因为每一个线程对象都有属于自己的一份 this,所以多个线程使用的不是同一个锁
    解决办法:使用 static 修饰同步函数,此时同步函数中的锁还是 this 吗?
    不是,因为 static 不能访问 this,锁是 类名.class
  • Lock 锁:
  • Lock 是一个接口,在 jdk 1.5 后出现,它使用了比 synchronized 更简单更广泛的锁的操作方式
  • 方法:lock() 获取锁,unlock() 释放锁
  • 步骤:
  • 在成员位置创建 ReentrantLock 对象
  • 在可能会发生线程安全问题前调用 lock() 获取锁
  • 在可能会发生线程安全问题后调用 unlock() 释放锁


  • 同步技术的原理:

    同步技术中使用到了锁对象,这个锁对象也称为同步锁

    多个线程一起抢夺 CPU 的执行权,谁抢到了,谁就能进入同步代码块,

    当一个线程抢夺到了 CPU 的执行权时,会判断是否有锁对象,

    如果有锁对象,就会获取到这个锁,进入同步代码块,当这个线程执行完同步代码块,就会释放锁

    如果没有锁对象,会处于阻塞状态,等待其他线程执行完同步代码块,等待其他线程释放锁,才能再进行 CPU 执行权的抢夺

    使用同步锁会影响程序的执行效率:

    因为获取 CPU 执行权的线程,在进入同步代码块之前,需要判断是否有锁,

    如果有锁还需要进行获取的动作,

    在执行完同步代码块后,需要释放锁。

    (判断锁,获取锁,释放锁)

    五,线程池

    5.1 问题

    在每次使用线程时,都需要创建线程对象,操作方式非常简便,但是存在一个问题:

    如果并发的线程数量很多,每个线程执行完一个时间很短的任务就结束了,这样频繁创建线程会极大的降低程序的性能。

    所以我们需要想一个办法能重复利用已创建的线程,来避免线程的过多创建。

    5.2 概念

    线程池本质上就是一个可以存放多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作。

    5.3 好处

  • 降低资源消耗,减少了创建线程的次数,每个线程都可以被重复利用
  • 提高程序的响应速度
  • 提高了对线程的管理

  • 5.4 实现步骤

  • 使用线程池的工厂类 Executors 中的静态方法 newFixedThreadPool 创建一个包含指定线程数量的线程池 ExecutorService
  • 创建 Runnable 接口的实现类,重写 run() 方法
  • 调用 ExecutorService 中的 submit() 方法,传入实现类对象,该方法用于开启线程并调用 run() 方法
  • 调用 ExecutorService 中的 shutdown() 方法,来销毁线程池,一旦被销毁,就无法再从池中获取线程对象


  • 上一篇:Java8-Optional类-ofNullable与orElseThrow
    下一篇:没有了
    网友评论