我今天要彻底搞懂线程状态的变化

💗推荐阅读文章💗

  • 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》
  • 🌺MySQL系列🌺👉2️⃣《MySQL系列教程》
  • 🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》
  • 🌻SSM框架系列🌻👉4️⃣《SSM框架系列教程》

🎉本博客知识点收录于🎉👉🚀《JavaSE系列教程》🚀—>✈️13【线程等待、状态、线程池、File类】✈️

文章目录

  • 二、线程状态
    • 2.1 线程状态
      • 2.1.1 NEW
      • 2.1.2 Runnable
      • 2.1.3 Blocked
      • 2.1.4 Timed Waiting
      • 2.1.5 Waiting
      • 2.1.6 Terminated
    • 2.2 线程状态变化
      • 2.2.1 线程状态的转变
        • 1)Runnable与Blocked状态转换
        • 2)Runnable与Waiting状态转换
        • 3)Runnable与Timed Waiting状态转换
      • 2.2.2 状态变化的注意事项

二、线程状态

2.1 线程状态

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,有几种状态呢?在API中java.lang.Thread.State这个枚举中给出了六种线程状态:

这里先列出各个线程状态发生的条件,下面将会对每种状态进行详细解析;

线程状态导致状态发生条件
NEW(新建)线程刚被创建,但是并未启动。还没调用start方法。
Runnable(可运行)线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
Blocked(锁阻塞)当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
Waiting(无限等待)一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
Timed Waiting(计时等待)同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
Teminated(被终止)因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

2.1.1 NEW

New(新建):表示线程被创建但尚未启动的状态:当我们用 new Thread() 新建一个线程时,如果线程没有开始运行 start() 方法,那么线程也就没有开始执行 run() 方法里面的代码,那么此时它的状态就是 New。而一旦线程调用了 start(),它的状态就会从 New 变成 Runnable

  • 示例代码:
package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_新建状态 {
    public static void main(String[] args) {
        Thread t1 = new Thread(){
            @Override
            public void run() {

            }
        };

        // 线程未启动之前的状态都是NEW
        System.out.println(t1.getState());          // NEW
    }
}

2.1.2 Runnable

Runnable被称为可运行状态,一旦线程调用start()方法,线程就处于可运行状态(Runnable)。

一个可运行的线程能正在运行也可能没有运行。有些教科书上讲可运行状态分为了就绪状态运行状态,即线程开启后进入就绪状态,当线程抢到CPU执行权后进入运行状态(Java规范没有将正在运行作为一个单独的状态,一个正在运行的线程仍然处于可运行状态)

  • 示例代码:
package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02_线程状态_RUNNABLE{
    public static void main(String[] args) {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                while (true){

                }
            }
        };

        Thread t2 = new Thread(){
            @Override
            public void run() {
                while (true){

                }
            }
        };

        t1.start();
        t2.start();

        // 线程只要开启之后不管是否处于运行状态

        System.out.println(t1.getState());          // RUNNABLE
        System.out.println(t2.getState());          // RUNNABLE
    }
}

2.1.3 Blocked

从 Runnable 状态进入到 Blocked 状态只有一种途径,那么就是当进入到 synchronized 代码块中时未能获得相应的锁,当有线程从 Blocked 状态指向了 Runnable ,也只有一种情况,那么就是当线程获得锁,此时线程就会进入 Runnable 状体中参与 CPU 资源的抢夺

【示例代码】

package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03_线程状态_RUNNABLE {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                synchronized (Object.class) {
                    while (true) {}
                }
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                // t2线程获取不到锁,被锁阻塞在外面
                synchronized (Object.class) {

                }
            }
        };

        t1.start();
        
        // 过一会再开启线程2(确保线程1必定先获取CPU执行权)
        Thread.sleep(100);
        
        t2.start();

        System.out.println(t1.getState());          // RUNNABLE
        System.out.println(t2.getState());          // BLOCKED
    }
}

2.1.4 Timed Waiting

Timed Waiting 状态,它与 Waiting 状态非常相似,其中的区别只在于是否有时间的限制,在 Timed Waiting 状态时会等待超时,之后由系统唤醒

在以下情况会让线程进入 Timed Waiting 状态。

  • 线程执行了设置了时间参数的 Thread.sleep(long millis) 方法;
  • 线程执行了设置了时间参数的 Object.wait(long timeout) 方法;
  • 线程执行了设置了时间参数的 Thread.join(long millis) 方法;

通过这个我们可以进一步看到它与 waiting 状态的相同


【示例代码1】:

package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04_线程状态_TIMED_WAITING {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };


        t1.start();

        // 让main线程睡眠一段时间(确保t1线程能够执行)
        Thread.sleep(100);

        System.out.println(t1.getState());          // TIMED_WAITING
    }
}

【示例代码2】

package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo05_线程状态_TIMED_WAITING_02 {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                synchronized (Object.class){
                    while (true){
                        try {
                            Object.class.wait(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        };


        t1.start();

        // 让main线程睡眠一段时间(确保t1线程能够执行)
        Thread.sleep(100);

        System.out.println(t1.getState());          // TIMED_WAITING
    }
}

【示例代码3】

package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo06_线程状态_TIMED_WAITING_03 {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                while (true) {
                }

            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    try {
                        // 让t1线程先执行10s,t2将处于TIMED_WAITING状态
                        t1.join(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        };
        t1.start();
        t2.start();

        // 让main线程睡眠0.1s,保证t1线程能执行join方法
        Thread.sleep(100);

        System.out.println(t1.getState());          // RUNNABLE
        System.out.println(t2.getState());          // TIMED_WAITING
    }
}

2.1.5 Waiting

对于 Waiting 状态的进入有2种情况,分别为:

  • 1)当线程中调用了没有设置 Timeout 参数的 Object.wait() 方法
  • 2)当线程调用了没有设置 Timeout 参数的 Thread.join() 方法
  • 3)当线程调用了 LockSupport.park() 方法

【示例代码1】:

package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo07_线程状态_WAITING {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                synchronized (Object.class) {
                    try {
                        Object.class.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        t1.start();

        // 让当前线程睡眠0.1s,确保t1线程能够执行wait
        Thread.sleep(100);

        System.out.println(t1.getState());          // WAITING
    }
}

【示例代码2】:

package com.dfbz.demo;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo08_线程状态_WAITING_02 {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                while (true){

                }
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        t1.start();
        t2.start();

        // 让当前线程睡眠0.1s,确保t1线程能够执行join
        Thread.sleep(100);

        System.out.println(t1.getState());          // RUNNABLE
        System.out.println(t2.getState());          // WAITING
    }
}

【示例代码3】:

package com.dfbz.demo;

import java.util.concurrent.locks.LockSupport;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo09_线程状态_WAITING_03 {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                while (true){
                    LockSupport.park();
                }
            }
        };

        t1.start();

        // 让当前线程睡眠0.1s,确保t1线程能够执行park
        Thread.sleep(100);

        System.out.println(t1.getState());          // WAITING
    }
}

Blocked与Waiting的区别:

  • Blocked 是在等待其他线程释放锁
  • Waiting 则是在等待某个条件,比如 join 的线程执行完毕,或者是 notify()/notifyAll() 。

2.1.6 Terminated

Terminated:终止状态,要想进入Terminated 状态有两种可能。

  • 1)run() 方法执行完毕,线程正常退出。
  • 2)出现一个没有捕获的异常,终止了 run() 方法,最终导致意外终止。

【示例代码】:

package com.dfbz.demo01_线程的等待与唤醒;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo10_线程状态_TERMINATED {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1 running...");
            }
        };

        t1.start();

        // 让当前线程睡眠10毫秒,确保t1线程任务执行完毕
        Thread.sleep(10);

        System.out.println(t1.getState());          // TERMINATED
    }
}

2.2 线程状态变化

线程流程图:

在这里插入图片描述

2.2.1 线程状态的转变

接下来我们将来分析各自状态之间的转换,其实主要就是 Blocked、waiting、Timed Waiting 三种状态的转换 ,以及他们是如何进入下一状态最终进入 Runnable

1)Runnable与Blocked状态转换

  • 1)Runnable状态进入Blocked状态:当前线程竞争锁对象失败时:Runnable-->Blocked
  • 2)Blocked状态进入Runnable状态:当之前的线程释放了锁对象时,新的线程竞争到了锁对象时:Blocked-->Runnable

【示例代码】:

package com.dfbz.demo02_线程状态的改变;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_Runnable进入Blocked状态 {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (obj) {
                while (true) {
                    System.out.println("t1");
                }
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            synchronized (obj) {
                while (true) {
                    System.out.println("t2");
                }
            }
        }, "t2");
        t1.start();
        t2.start();
    }
}

在这里插入图片描述

2)Runnable与Waiting状态转换

如果通过其他线程调用 notify() 或 notifyAll()来唤醒它,则它会直接进入Blocked状态,这里可能会有疑问,不是应该直接进入 Runnable 吗?

这里需要注意一点 ,因为唤醒 Waiting 线程的线程如果调用 notify() 或 notifyAll(),要求必须首先持有该锁,这也就是我们说的 wait()、notify 必须在 synchronized 代码块中。

所以处于 Waiting 状态的线程被唤醒时拿不到该锁,就会进入 Blocked 状态,直到执行了 notify()/notifyAll() 的唤醒它的线程执行完毕并释放锁,才可能轮到它去抢夺这把锁,如果它能抢到,就会从 Blocked 状态回到 Runnable 状态。

【示例代码】:

package com.dfbz.demo02_线程状态的改变;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (obj) {
                System.out.println("t1-before..");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1-after..");
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            synchronized (obj) {
                System.out.println("t2-before..");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2-after..");
            }
        }, "t2");

        t1.start();
        t2.start();

        new Thread(){
            @Override
            public void run() {
                synchronized (obj){
                    // 将所有线程都唤醒,唤醒的线程都将处于blocked状态,因为要等当前线程释放锁对象
                    obj.notifyAll();
                }
            }
        }.start();
    }
}

Tips:当我们通过 notify 唤醒时,是先进入锁阻塞状态的 ,再等抢夺到锁后才会进入 Runnable 状态!

Runnable状态进入Waiting状态有三种情况:

  • 1)调用wait方法进入Waiting状态
    • 返回Runnable状态使用notifly或notifyAll方法(需要注意的是先进入Blocked再进入Runnable)
  • 2)调用join方法进入Waiting状态
    • 返回Runnable状态使用interrupt()方法中断线程
  • 3)调用park方法进入Waiting状态
    • 返回Runnable状态使用interrupt()方法中断线程

【示例代码1】:

package com.dfbz.demo02_线程状态的改变;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (obj) {
                System.out.println("t1-before..");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1-after..");
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            synchronized (obj) {
                System.out.println("t2-before..");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2-after..");
            }
        }, "t2");

        t1.start();
        t2.start();

        new Thread(){
            @Override
            public void run() {
                synchronized (obj){
                    // 将所有线程都唤醒,唤醒的线程都将处于blocked状态,因为要等当前线程释放锁对象
                    obj.notifyAll();
                }
            }
        }.start();
    }
}

【示例代码2】:

package com.dfbz.demo02_线程状态的改变;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                while (true){

                }
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                System.out.println("t2-before...");
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2-after...");
            }
        };

        t1.start();
        t2.start();

        // 让当前线程睡眠0.1s,确保t1线程能够执行join
        Thread.sleep(100);

        System.out.println(t1.getState());          // RUNNABLE
        System.out.println(t2.getState());          // WAITING

        System.out.println(t2.isInterrupted());

        // 打断t2线程,t2线程将会处于Runnable状态
        t2.interrupt();

        System.out.println(t2.isInterrupted());
    }
}

【示例代码3】:

package com.dfbz.demo02_线程状态的改变;

import java.util.concurrent.locks.LockSupport;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
               while (true){
                   System.out.println("t1-before");
                   LockSupport.park();
                   System.out.println("t1-after");
               }
            }
        };

        t1.start();

        // 线程中断后,将会t1线程将会从Waiting状态转换为Runnable状态
        t1.interrupt();
    }
}

3)Runnable与Timed Waiting状态转换

Runnable状态进入Timed Waiting状态有三种情况:

  • 1)线程执行了设置了时间参数的 Thread.sleep(long millis) 方法;

    • 返回Runnable状态:
      • 1)等到millis时间到达
      • 2)使用interrupt中断线程(中断标记还是false)
  • 2)线程执行了设置了时间参数的 Object.wait(long timeout) 方法;

    • 返回Runnable状态:
      • 1)等到timeout时间到达
      • 2)使用interrupt中断线程(中断标记还是false)
      • 3)使用notifly或notiflyAll唤醒(首先进入Blocked状态,竞争到锁之后再进入Runnable状态)
  • 3)线程执行了设置了时间参数的 Thread.join(long millis) 方法;

    • 1)等到timeout时间到达
    • 2)使用interrupt中断线程(中断标记还是false)
    • 3)使用notifly或notiflyAll唤醒(首先进入Blocked状态,竞争到锁之后再进入Runnable状态)

Tips:notifly和notiflyAll只能唤醒使用wait方法进行等待的线程;

【示例代码1】:

1)测试sleep方法时间到达后线程状态从Timed Waiting变为Runnable

2)测试调用interrupt()方法将线程状态从Timed Waiting变为Runnable

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                System.out.println("t1-before...");
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1-after...");
            }
        };

        t1.start();

        // 中断t1线程(t1线程的中断标记还是false),t1线程抛出异常后又恢复为Runnable状态
        t1.interrupt();
    }
}

【示例代码2-1】:

1)测试wait方法时间到达后线程状态从Timed Waiting变为Runnable

2)测试调用interrupt()方法将线程状态从Timed Waiting变为Runnable

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                synchronized (Object.class){
                    System.out.println("t1-before...");
                    try {
                        // 等到wait的时间到达之后线程自动从Timed Waiting状态变为Runnable状态
                        Object.class.wait(30000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1-after...");
                }
            }
        };

        t1.start();

        // 中断t1线程(t1线程的中断标记还是false),t1线程抛出异常后又恢复为Runnable状态
        t1.interrupt();
    }
}

【示例代码2-2】:使用notify/notiflyAll将线程状态从Timed Waiting变为Runnable(Blocked)

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                synchronized (Object.class){
                    System.out.println("t1-before...");
                    try {
                        // 等到wait的时间到达之后线程自动从Timed Waiting状态变为Runnable状态
                        Object.class.wait(30000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1-after...");
                }
            }
        };

        t1.start();

        // 让main线程睡眠10毫秒,确保t1线程能够先执行
        Thread.sleep(10);
        
        synchronized (Object.class){
            Object.class.notifyAll();
        }
    }
}

【示例代码3】:

1)测试join方法时间到达后线程状态从Timed Waiting变为Runnable

2)测试调用interrupt()方法将线程状态从Timed Waiting变为Runnable

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                while (true){}
            }
        };
        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                try {
                    t1.join(3000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("t2-after..");
            }
        };

        t1.start();
        t2.start();

        // 让main线程睡眠10毫秒,确保t1和t2线程先执行
        Thread.sleep(10);

        t2.interrupt();
    }
}

2.2.2 状态变化的注意事项

  • 1)线程从 New 状态是不可以直接进入 Blocked 状态的,它需要先经历 Runnable 状态。
  • 2)线程生命周期不可逆,一旦进入 Runnable 状态就不能回到 New 状态;一旦被终止就不可能再有任何状态的变化。
  • 3)所以一个线程只能有一次 New 和 Terminated 状态,只有处于中间状态才可以相互转换。也就是这两个状态不会参与相互转化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/68.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB | 这些花里胡哨的热图怎么画

好早之前写过一个绘制相关系数矩阵的代码,但是会自动求相关系数,而且画出来的热图只能是方形,这里写一款允许nan值出现,任意形状的热图绘制代码,绘制效果如下: 如遇到bug请后台提出,并去gitee下…

出道即封神的ChatGPT,现在怎么样了?

从互联网的普及到智能手机,都让广袤的世界触手而及,如今身在浪潮中的我们,已深知其力。前阵子爆火的ChatGPT,不少人保持观望态度。现如今,国内关于ChatGPT的各大社群讨论,似乎沉寂了不少,现在怎…

Linux IPC:匿名管道 与 命名管道

目录一、管道的理解二、匿名管道三、命名管道四、管道的通信流程五、管道的特性进程间通信方式有多种,本文介绍的是管道,管道分为匿名管道和命名管道。 一、管道的理解 生活中的管道用来传输资源,例如水、石油之类的资源。而进程间通信的管道…

学习C++这几个网站足矣

文章目录cppreferencecplusplus[C 之父的网站](https://www.stroustrup.com/bs_faq.html)C提案[Cpp Core Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)[C Super-FAQ](https://isocpp.org/faq)[learn c](https://www.learncpp.com/)[Awesome C](h…

【YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进NO.59】引入ASPP模块

前言作为当前先进的深度学习目标检测算法YOLOv8,已经集合了大量的trick,但是还是有提高和改进的空间,针对具体应用场景下的检测难点,可以不同的改进方法。此后的系列文章,将重点对YOLOv8的如何改进进行详细的介绍&…

1.10-1.12 Makefile

1. Makefile简介 举个栗子,如下为redis-5.0.10的项目目录,有很多的文件 有了Makefile文件,可以简单的make一下就可以对项目文件进行编译,最终生成可执行程序。 2. Makefile栗子1 首先,创建vim Makefile按照PPT里的格…

C++STL set/multiset容器 构造和赋值 大小和交换 插入和删除 查找和统计

文章目录set/multiset容器1 set容器 基本概念2 set容器 构造和赋值3 set容器 大小和交换4 set容器 插入和删除5 set容器 查找和统计set/multiset容器 1 set容器 基本概念 简介: 所有元素都会在插入时会被自动排序,例如,在set容器放入元素1、…

成本降低90%,OpenAI正式开放ChαtGΡΤ

今天凌晨,OpenAI官方发布ChαtGΡΤ和Whisper的接囗,开发人员现在可以通过API使用最新的文本生成和语音转文本功能。OpenAI称:通过一系列系统级优化,自去年12月以来,ChαtGΡΤ的成本降低了90%;现在OpenAI用…

公网远程连接Oracle数据库【内网穿透】

文章目录1. 数据库搭建2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射3. 公网远程访问4. 配置固定TCP端口地址4.1 保留一个固定的公网TCP端口地址4.2 配置固定公网TCP端口地址4.3 测试使用固定TCP端口地址远程OracleOracle,是甲骨文公司的一款关系数据库管理系…

【前端vue2面试题】2023前端最新版vue2模块,高频24问

​ 🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:博主收集的关于vue2面试题 目录 vue2面试题 1、$route 和 $router的区别 2、一个.v…

2月更新 | Visual Studio Code Python

我们很高兴地宣布,2023年2月版 Visual Studio Code Python 和 Jupyter 扩展现已推出!此版本包括以下改进:从激活的终端启动 VS Code 时的自动选择环境 使用命令 Python: Create Environmen 时可选择需求文件或可选依赖项 预发布:改…

java八股文--java基础

java基础1.什么是面向对象,谈谈对面向对象的理解2.JDK JRE JVM的区别与联系3.和equals4.hashCode与equals5.String StringBuffer StringBuilder的区别6.重载和重写的区别7.接口和抽象类8.List和Set的区别9.ArrayList和LinkedList10.HashMap和HashTable的区别&#x…

2023.03.12学习总结

项目部分写了内外菜单栏的伸缩,更新了导航栏,新增配置,scss变量 提交记录 学习了scss的使用和配置 ,设置了scss全局变量,组件样式 给element-plus配置了主题颜色,配置到了全局 http://t.csdn.cn/FhZYa …

【PyTorch】Pytorch基础第0章

本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052 这是目录PyTorch的简介PyTorch 构建深度学习模型的步骤搭建pytorch使用环境PyTorch的简介 PyTorch 是一个开源的机器学习框架,由 Facebook 的人工智能研究院(…

面部表情识别2:Pytorch实现表情识别(含表情识别数据集和训练代码)

面部表情识别2:Pytorch实现表情识别(含表情识别数据集和训练代码) 目录 面部表情识别2:Pytorch实现表情识别(含表情识别数据集和训练代码) 1.面部表情识别方法 2.面部表情识别数据集 (1)表情识别数据集说明 (2&…

蔬菜视觉分拣机器人的设计与实现(RoboWork参赛方案)

蔬菜视觉分拣机器人的设计与实现 文章目录蔬菜视觉分拣机器人的设计与实现1. 技术栈背景2. 整体设计3. 机械结构3.1 整体结构3.2 底座结构3.3 小臂结构3.4 大臂结构3.5 负载组件结构3.6 末端执行器结构4. 硬件部分4.1 视觉系统4.1.1 光源4.1.2 海康工业相机4.2 传送带系统4.2.1…

网络工程师必备知识点

作为网络工程师,您将负责设计、部署和维护计算机网络系统。这包括构建、配置和管理网络设备,如交换机、路由器、防火墙等,并确保网络系统能够高效地运行。您需要了解计算机网络的各个层次、协议、标准和技术,包括TCP/IP、DNS、HTT…

现在的00后,实在是太卷了

现在的小年轻真的卷得过分了。前段时间我们公司来了个00年的,工作没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天,原来这位小老弟家里条…

CPU平均负载高问题定位分析

一、Linux操作系统CPU平均负载 1.1什么是CPU平均负载 1.2 怎么查看平均负载数值 二、Linux操作系统CPU使用率和平均负载区别 CPU使用率和平均负载区别 三、阿里云Linux操作系统CPU压测环境准备 3.1 核心命令应用场景 3.2 模拟生产环境出现的多种问题环境准备 分析工具安…

我,30岁程序员被裁了,千万别干全栈

大家好,这里是程序员晚枫,今天是读者投稿。下面开始我们的正文。👇 关注博主👉程序员晚枫 很久了,今天给大家分享一下我从事程序员后,30岁被裁的经历,希望帮到有需要的人。 1、我被裁了 大家好…