• Java基础|Java并发相关api


    ​ java线程相关的包是java.util.concurrent,也就是大名鼎鼎的juc,线程同步的相关类与接口都在这个包里。java关于线程同步的问题设计了一个关键字,叫做synchronized,利用这个关键字可以避免多线程情况下的脏数据问题,使用方法很简单,就是在后面的参数里填上同步监视器(俗称“锁”),当锁没有被任何线程占用时,任何线程都可以将锁握住。当锁被握住时,其他进程无法拥有锁,进而无法进入synchronized关键字规定的同步区域中,无锁的进程被阻塞,等待锁被释放出来再次去争夺锁。(说白了就是锁内区域代码都是单线程,无法并发执行)
    ​ 为了编码更复杂的代码,java引入了等待与超时等待两个状态,当拥有锁的进程通过锁去调用wait()方法时,就会进入等待或超时等待的状态,此时该线程锁拥有的锁将被释放,重新被剩余的线程锁争夺,该线程该如何回到runnable呢?需要该锁去调用notify()才可。当然,除了wait和notify外,还有许多进入和出去wait状态的方法。

    api介绍

    操作线程有两个地方,一个是父类object中定义的wait()等方法,另一个是Thread类中定义的相关方法。

    Thread类中定义的关于线程的api

    1. start():重启当前线程;调用当前线程的run()
    2. run():通常需要重写Thread类中的方法,将创建的线程要执行的操作声明再此方法中
      这个方法开发者很少调用,因为这是线程的方法的容器,直接调用只是普通的调用方法而已,不能开启新线程,开启新线程需要调用start()这个方法。
    3. getName():获取当前线程的名字
    4. setName():设置当前线程的名字
    5. currentThread():静态方法,返回当前代码执行的线程,是一个Thread类型

    下面的方法理解起来比较复杂

    1. yield():静态方法,让 当前线程 让出cpu运算执行权,调用此方法后,会将当前线程挂起,也就是从运行中转到就绪态,后面的指令仍旧会执行,只不过暂停在此处了,等cpu分配到这个线程,继续从此处开始,但是!不一定可以成功,是否成功需要看条件,我试了一下,没成功。这方法没什么用(开发者而言)

    在这里插入图片描述

    1. join():要求调入其他线程的方法,该线程让步
      使用线程的对象进行调用,例如一个线程类对象Thread t1,t1.join(),这样用,那么这行代码下面的代码必须等t1这个线程执行完才可以继续执行,下面是一个小例子

      public class Test1 implements Runnable {
          @Override
          public void run() {
              try {
                  sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println(currentThread()+"over");
          }
          public static void main(String[] args) throws InterruptedException, ExecutionException {
              Test1 test1 = new Test1();
              Thread t1 = new Thread(test1);
              Thread t2 = new Thread(test1);
              t1.start();
              t2.start();
              //如果没有调用join方法,那么System.out.println(currentThread());必定是在两个线程前执行
              t1.join();
              t2.join();
              System.out.println(currentThread());
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
    2. stop():已过时,强制结束当前线程

    3. sleep(long millitime):让当前线程“睡眠”制定的毫秒,停设置的毫秒数

    4. isAlive():判断是否存活

    5. 优先级:
      MAX_PRIORITY :10
      MIN PRIORITY :1
      NORM_PRIORITY :5 默认是5
      设置方法:

      getPriority ():返回线程优先值
      setPriority (int newPriority ): 改变线程的优先级
      
      • 1
      • 2

    Object类下面的方法

    wait() / notify() / notifyAll()

    ​ 线程状态转换:就线程自己的控制,不直接涉及别的线程

    wait方法可以控制当前的线程,因为调用wait方法会使得当前线程阻塞,释放同步锁,不过是否会对其他线程产生影响是取决于程序设计。如果别的线程需要这把锁,那么这两个线程就关联起来了,这从整体上来看就是线程A阻塞,释放锁,线程B握锁进入同步方法。

    ​ wait()会释放锁,用notify()会恢复(使用流程见ppt画板)

    释义:wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
    ​ notify():执行此方法,唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的。(notify后的线程直接退出当前同步方法体。)
    ​ notifyAll():唤醒所有的线程。

    注意:

    1. 以上3个方法的使用前提:必须使用在同步代码块或同步方法中(synchronize)
    2. 调用要求:三个方法的调用者,必须是同步监视器(对象),否则会出现IllegalMonitorStateException。
    3. 因为要保证任何一个方法都有notify(),notifyAll(),这三个方法是定义在Java.lang.Object类中的。
  • 相关阅读:
    两个部门,六轮面试,终与字节无缘
    潘多拉 IOT 开发板学习(HAL 库)—— 实验1 跑马灯(RGB)实验(学习笔记)
    【项目】5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型
    strlen简介,和sizeof的区别
    矢量化的步骤
    036:vue导出页面生成pdf文件
    Sentinel底层原理(下)
    被遗忘的艺术:图的思维方式
    全面升级!Apache HugeGraph 1.2.0版本发布
    大模型LLM相关面试题整理
  • 原文地址:https://blog.csdn.net/weixin_48118167/article/details/126588379