多线程原理详解01(程序、进程、线程介绍,线程创建的三种方式(Thread、Runnable、Callable)、三种方式各自实现多线程的具体操作、代码解析)

目录

  • 多线程原理详解
    • 01_线程简介
      • 多任务
      • 多线程
      • 程序、进程、线程
      • Process(进程)与 Thread (线程)
      • 总结:
    • 02_线程创建三种方式:
      • 1、继承 Thread 类
        • 1-1:通过继承Thread类实现多线程
          • 演示代码
        • 1-2:演示多线程同步下载图片:
          • 演示代码
      • 2、实现 Runnable 接口 (推荐)
        • 2-1:通过实现Runnable接口来实现多线程
          • 具体代码
        • 2-2:通过实现Runnable接口来实现多线程同步下载图片
          • 具体代码
        • 2-3:演示多个线程同时操作同一个对象出现的并发问题
          • 演示买火车票的例子
            • 具体代码
          • 通过 synchronized 关键字同步代码块解决并发问题
            • 具体代码
        • 2-4:演示龟兔赛跑案例
          • 用多线程的方式模拟龟兔赛跑代码分析
          • 具体代码
      • 3、实现 Callable 接口
        • 演示多线程同时下载图片
        • 具体代码
      • 4、总结:三种创建方式的区别:

多线程原理详解


01_线程简介

任务、进程、线程、多线程


多任务

就是在一个时间内做很多事情,比如边吃饭变玩手机,但是本质上,在那一秒内,其实只是在玩手机,或者在一秒内只是在吃饭。
看起来像是多个任务都在做,其实本质上我们的大脑在同一时间依旧只做了一件事情而已

在这里插入图片描述


多线程

比如原本一条道路看成一个线程,多辆车都在一个道路上形式,容易出问题。
但是如果给道路划分路线,相当于弄多条线程,让多辆车在各自的线程行驶,出问题的概率就变小。
在这里插入图片描述

平常项目中的普通的方法调用,基本是一条线程走到底,即使调用方法,也是在方法执行完后继续往下走,只用到主线程而已。

多线程就是多条线程各自执行,效率更高。

就像一个大超市,只有一个收银员(单线程)和多个收银员(多线程)的区别。

在这里插入图片描述


程序、进程、线程

在操作系统中运行的程序就是进程,比如微信、QQ、腾讯视频、游戏这些就是程序,也就是进程

一个进程(腾讯视频)可以有多个线程(视频声音、图像、弹幕等)

在这里插入图片描述


Process(进程)与 Thread (线程)

程序(静态的)–>程序跑起来变成进程(动态的)–>进程里面包含多个线程,真正执行功能的就是这些线程

在这里插入图片描述


总结:

在这里插入图片描述

注意:

单核 CPU 上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。

多核 CPU 上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核 CPU 的优势来,达到充分利用 CPU 的目的



02_线程创建三种方式:

三种创建方式主要是:继承 Thread 类、实现 Runnable 接口,还有一个是 实现 Callable 接口

最好的是实现 Runnable 接口,因为实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度。

这三种方式都能开启多个线程来执行业务逻辑。


1、继承 Thread 类

步骤:

1、自定义一个类,继承 Thread 类;
2、重写 run() 方法,编写线程执行体;
3、创建线程对象,调用 start() 方法启动线程;


解释:

自定义一个类去继承Thread 类,作为一个线程类对象,然后就可以重写Thread类的 run() 方法;
接着在main主线程里面,可以通过线程对象去调用 start() 方法,该方法的作用是让 java 虚拟机去启动一个新的线程去执行 run() 方法里面的代码。
然后主线程继续执行自己的业务代码。

这样主线程和新的线程就都同时执行,这个就是多线程操作。


1-1:通过继承Thread类实现多线程

当我们调用 start() 方法后,start() 方法会通知 Java 虚拟机启动一个新线程(也就是子线程),并在新线程中调用该线程对象(t1)的 run() 方法。

而主线程调用start() 方法后,也会继续执行下面的代码。

这个时候,主线程和新线程就会并发执行,这样就演示出了多线程并发执行的特性。

在这里插入图片描述


演示代码

//创建线程方式一:继承 Thread 类, 重写 run() 方法,调用 start() 方法开启线程
//注意:线程开启不一定立即执行,由 CPU 调度执行
public class TestThread01 extends Thread
{
    //重写 run() 方法
    @Override
    public void run()
    {
        //run 方法线程体
        for (int i = 0; i < 20; i++)
        {
            System.err.println("run方法线程:bbbbbb--->" + i);
        }

    }

    //main 主线程
    public static void main(String[] args)
    {
        //创建一个线程对象
        TestThread01 t1 = new TestThread01();

        //直接调用run方法,只是普通的调用,跟多线程没有关系
        //t1.run();

        //调用start()方法开启线程,主线程和run()方法的线程就会同时进行
        t1.start();

        for (int i = 0; i < 20; i++)
        {
            System.err.println("main主线程:aaaaaaaaaa--->" + i);
        }
    }

}

1-2:演示多线程同步下载图片:

先下载一个 Apache 的 Commons IO 的 jar 包,是一个文件下载的工具类库

在这里插入图片描述

下载之后解压,把这个 jar 包拷贝到项目里面去

在这里插入图片描述

点击右键,点击【Add library】添加进去即可。
有了这个工具类库,才可以使用比如 FileUtils 这样的工具类

在这里插入图片描述


代码实现:

代码中,可以看出如果是单线程下载这3张图片的话,下载顺序应该是1、2、3
可从结果看,下载顺序是3、2、1,说明是多线程在同步下载图片,哪条线程快就哪条先下载完。

在这里插入图片描述


如图,图片成功下载下来了,这图片是我其他 博客文章里面的图片

在这里插入图片描述


演示代码
package cn.ljh.threaddemo.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;

// 实现多线程同步下载图片
public class TestThread02 extends Thread
{
    private String url; //网络图片地址
    private String name;//保存的文件名

    //构造器
    public TestThread02(String url ,String name){
        this.url = url;
        this.name = name;
    }

    //重写run方法
    @Override
    public void run()
    {
        //run方法里面调用了文件下载的downloader方法
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url,name);
        System.err.println("下载了文件名为:"+ name);
    }

    //主线程
    public static void main(String[] args)
    {
        //创建三个线程对象
        TestThread02 t1 = new TestThread02(
                "https://img-blog.csdnimg.cn/direct/0aded64215424e0488d3da76357750b6.png",
                "1.jpg");
        TestThread02 t2 = new TestThread02(
                "https://img-blog.csdnimg.cn/direct/0aded64215424e0488d3da76357750b6.png",
                "2.jpg");
        TestThread02 t3 = new TestThread02(
                "https://img-blog.csdnimg.cn/direct/0aded64215424e0488d3da76357750b6.png",
                "3.jpg");
        //启动3条线程
        t1.start();
        t2.start();
        t3.start();
    }
}


//图片下载器
class WebDownloader{

    //下载方法
    public void downloader(String url,String  name){
        try
        {
            //把网络图片地址url变成一个文件,参数1:网络图片地址 ;参数2:下载后保存的文件名
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e)
        {
            e.printStackTrace();
            System.err.println("IO异常,downloader 方法出现问题");
        }
    }

}


2、实现 Runnable 接口 (推荐)

步骤:

1、自定义一个类,实现 Runnable 接口;
2、实现 run() 方法,编写线程执行体;
3、创建线程对象,调用 start() 方法启动线程;


2-1:通过实现Runnable接口来实现多线程

这个和上面继承 Thread 类的操作差别不大。

如图:这个实现了Runnable接口的自定义线程类TestThread03,作为参数传进到 Thread 这个线程对象里面,然后通过 Thread 这个线程对象调用 start() 方法启动新线程。

解释下这个自定义线程类TestThread03,为什么说它是一个代理对象。

详细解释:

代码中:
将 t 视为一个代理对象的原因是它充当了线程对象(thread)和具体任务逻辑之间的中介。

具体来说,t 自定义线程类对象 实现了 Runnable 接口,并在其 run() 方法中定义了线程要执行的任务逻辑。

当我们通过 Thread 类创建一个 thread 对象时,需要将一个实现了 Runnable接口的对象(t)作为参数传入,那么这个对象(t)就是线程对象(thread)的代理,它 (t) 负责管理线程的生命周期和执行任务的逻辑。

在调用 thread.start() 方法后,线程对象(thread)会自动调用代理对象(t)的 run() 方法,从而执行具体的任务逻辑。

t 作为一个代理对象,充当了线程对象(thread)和具体任务逻辑之间的桥梁,使得线程的管理和任务的执行能够分开进行,提高了代码的灵活性和可维护性。

简单来说:

实现了Runnable接口的t对象,它实现了run()方法,作用是在run()方法里面写具体的业务逻辑代码。

而创建一个 Thread 对象,作用是用来调用 start() 方法从而启动新线程。

而启动的新线程要执行的业务逻辑代码在t对象的run()方法里面,所以就把 t 作为代理对象传给 thread 对象。

这样就是通过代理的方式实现了线程的启动(thread.start())和任务(任务在run()方法里面)的执行。

在这里插入图片描述

和上面的继承 Thread 类差不多。

再简洁的说法:

继承 Thread 类的自定义线程类对象,是自身调用 start 方法启动新线程。

实现Runnable 接口的自定义线程类对象,是作为创建Thread线程对象的参数,由Thread线程对象来调用start方法启动新线程


具体代码
package cn.ljh.threaddemo.demo01;

//创建线程方式2:实现 Runnable 接口,重写 run 方法,执行线程需要丢入 runnable 接口实现类,调用 start 方法

public class TestThread03 implements Runnable
{
    //实现 run() 方法
    @Override
    public void run()
    {
        //run 方法线程体
        for (int i = 0; i < 20; i++)
        {
            System.err.println("run方法线程:bbbbbb--->" + i);
        }
    }

    //main 主线程
    public static void main(String[] args)
    {
        //创建 Runnable 接口的实现类对象
        TestThread03 t = new TestThread03();

        //创建线程对象,通过线程对象thread来开启我们的线程---代理对象t
        Thread thread = new Thread(t);

        thread.start();

        for (int i = 0; i < 20; i++)
        {
            System.err.println("main主线程:aaaaaaaaaa--->" + i);
        }
    }
}


2-2:通过实现Runnable接口来实现多线程同步下载图片

小小区别:

在这里插入图片描述


具体代码
// 实现多线程同步下载图片
public class TestThread04 implements Runnable
{
    private String url; //网络图片地址
    private String name;//保存的文件名
    
    //构造器
    public TestThread04(String url ,String name){
        this.url = url;
        this.name = name;
    }
    
    //重写run方法
    @Override
    public void run()
    {
        //run方法里面调用了文件下载的downloader方法
        WebDownloader04 webDownloader = new WebDownloader04();
        webDownloader.downloader(url,name);
        System.err.println("下载了文件名为:"+ name);
    }
    
    //主线程
    public static void main(String[] args)
    {
        //创建三个线程对象
        TestThread04 t1 = new TestThread04(
                "https://img-blog.csdnimg.cn/direct/0aded64215424e0488d3da76357750b6.png",
                "1.jpg");
        TestThread04 t2 = new TestThread04(
                "https://img-blog.csdnimg.cn/direct/0aded64215424e0488d3da76357750b6.png",
                "2.jpg");
        TestThread04 t3 = new TestThread04(
                "https://img-blog.csdnimg.cn/direct/0aded64215424e0488d3da76357750b6.png",
                "3.jpg");
        //通过线程对象启动3条线程
        Thread thread = new Thread(t1);
        thread.start();
        new Thread(t2).start();
        new Thread(t3).start();
    }
}

//图片下载器
class WebDownloader04{
    //下载方法
    public void downloader(String url,String  name){
        try
        {
            //把网络图片地址url变成一个文件,参数1:网络图片地址 ;参数2:下载后保存的文件名
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e)
        {
            e.printStackTrace();
            System.err.println("IO异常,downloader 方法出现问题");
        }
    }
}


2-3:演示多个线程同时操作同一个对象出现的并发问题

演示买火车票的例子

演示多个线程同时操作同一个对象—以买火车票为例子

多个线程操作同一个资源的情况下,线程不安全,数据紊乱,
这个就是多线程情况下会出现的并发问题。

在这里插入图片描述


具体代码
//演示多个线程同时操作同一个对象---以买火车票为例子
//出现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱
public class TestThread05 implements Runnable
{
    //票数
    private int ticketNums = 10;

    @Override
    public void run()
    {
        while (true){
            if (ticketNums<=0){
                //终止当前所在循环
                break;
            }
            //模拟延迟
            try
            {
                Thread.sleep(500);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            System.err.println(Thread.currentThread().getName()+"--->买到了第【 "+ticketNums-- + " 】张票");
        }
    }

    public static void main(String[] args)
    {
        TestThread05 t = new TestThread05();
        //启动新线程  参数1:t 就是代理对象   参数2:name 就是当前线程名字
        new Thread(t,"小黄").start();
        new Thread(t,"小白").start();
        new Thread(t,"小绿").start();
    }
}

通过 synchronized 关键字同步代码块解决并发问题

简单解决下上面买车票的并发问题:

使用 synchronized 保证同一时间只有一个线程能来操作这个代码块。

在这里插入图片描述


具体代码
package cn.ljh.threaddemo.demo01;


//演示多个线程同时操作同一个对象---以买火车票为例子
//出现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱
public class TestThread05 implements Runnable
{
    //票数
    private int ticketNums = 10;

    @Override
    public void run()
    {
        while (true)
        {
            synchronized (this)
            {
                if (ticketNums <= 0)
                {
                    //终止当前所在循环
                    break;
                }
                System.err.println(Thread.currentThread().getName()
                        + "--->买到了第【 " + ticketNums-- + " 】张票");

            }
            //模拟延迟
            try
            {
                Thread.sleep(500);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args)
    {
        TestThread05 t = new TestThread05();
        //启动新线程  参数1:t 就是代理对象   参数2:name 就是当前线程名字
        Thread t1 = new Thread(t, "小黄");
        Thread t2 = new Thread(t, "小白");
        Thread t3 = new Thread(t, "小绿");

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

2-4:演示龟兔赛跑案例

自定义一个线程类,实现 Runnable 接口,然后启动两个线程(一个兔子线程和一个乌龟线程),用for循环,看哪个线程先执行到100米。

在这里插入图片描述


用多线程的方式模拟龟兔赛跑代码分析

在这里插入图片描述


具体代码

// 模拟龟兔赛跑案例
public class Race implements Runnable
{
    //胜利者
    private static String winner;

    //实现 run() 方法
    @Override
    public void run()
    {
        for (int i = 0; i <= 100; i++)
        {
            //模拟兔子休息--当前线程是"兔子" 并且 每跑10步,就休息一会
            if (Thread.currentThread().getName().equals("兔子") && i%10==0){
                try
                {
                    Thread.sleep(5);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }

            //判断比赛是否结束
            boolean flag = gameOver(i);
            //如果flag为true,表示比赛结束,直接终止当前所在循环
            if (flag){
                break;
            }
            System.err.println(Thread.currentThread().getName()
                    + " ---> 跑了【 " + i + " 】步");
        }

    }
    
    //主线程
    public static void main(String[] args)
    {

        Race race = new Race();
        //启动名为兔子的新线程
        new Thread(race, "兔子").start();
        //启动名为乌龟的新线程
        new Thread(race, "乌龟").start();

    }
    
    //判断是否完成比赛的方法
    public boolean gameOver(int steps)
    {
        //判断是否有胜利者
        if (winner != null)
        {
            //已经存在胜利者了,返回true
            return true;
        } else if (steps >= 100)
        {
            winner = Thread.currentThread().getName();
            System.err.println("胜利者是:【 " + winner + " 】");
            return true;
        }
        return false;
    }
}


3、实现 Callable 接口

步骤:

在这里插入图片描述


演示多线程同时下载图片

演示的依然是这个多线程同时下载图片的功能,不过这里是实现 Callable 接口。

这里的多线程操作,是通过创建一个线程池,然后把实现了 Callable 接口的自定义线程类对象(t1、t2、t3)作为任务参数提交给线程池去执行,并且可以获取线程执行后的结果,最后关闭线程池。

t1、t2、t3各自代表一个任务,它们实现了Callable接口,并且在call()方法中定义了具体的任务逻辑。
提交t1、t2、t3任务给线程池后,线程池会负责安排线程来执行t1、t2、t3中定义的任务逻辑。

在这里插入图片描述

通过源码可以看出 ,Callable 接口里面只有一个 call() 方法需要重写
在这里插入图片描述


具体代码
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

//线程创建方式三:实现 Callable 接口
/**
 * Callable 的好处
 * 1、可以定义返回值
 * 2、可以抛出异常
 */

// 实现多线程同步下载图片
public class TestCallable implements Callable<Boolean>
{
    private String url; //网络图片地址
    private String name;//保存的文件名

    //构造器
    public TestCallable(String url, String name)
    {
        this.url = url;
        this.name = name;
    }

    //实现 Call 方法
    @Override
    public Boolean call() throws Exception
    {
        //run方法里面调用了文件下载的downloader方法
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.err.println("下载了文件名为:" + name);

        //返回true表示任务执行成功
        return true;
    }

    //主线程
    public static void main(String[] args) throws Exception
    {
        //创建三个线程对象
        TestCallable t1 = new TestCallable(
                "https://img-blog.csdnimg.cn/direct/beb94daf07094fd5979693243c8ac60b.png",
                "1.jpg");
        TestCallable t2 = new TestCallable(
                "https://img-blog.csdnimg.cn/direct/beb94daf07094fd5979693243c8ac60b.png",
                "2.jpg");
        TestCallable t3 = new TestCallable(
                "https://img-blog.csdnimg.cn/direct/beb94daf07094fd5979693243c8ac60b.png",
                "3.jpg");

        //ExecutorService是Java中用于管理线程池的接口,通过ExecutorService,可以创建一个线程池,并使用该线程池执行任务

        // 1、创建执行服务:创建了一个固定大小为3的线程池,这意味着该线程池最多同时运行3个线程    fixed:固定的
        ExecutorService ser = Executors.newFixedThreadPool(3);

        // 2、提交执行:使用ExecutorService的submit()方法提交了三个任务(t1、t2、t3)给线程池执行,并且通过Future对象(r1、r2、r3)接收返回结果
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        // 3、获取返回值结果
        Boolean result1 = r1.get();
        Boolean result2 = r2.get();
        Boolean result3 = r3.get();

        System.err.println(result1);
        System.err.println(result2);
        System.err.println(result3);

        // 4、关闭服务,也就是关闭线程池
        ser.shutdown();

    }

    //图片下载器
    class WebDownloader
    {
        //下载方法
        public void downloader(String url, String name)
        {
            try
            {
                //把网络图片地址url变成一个文件,参数1:网络图片地址 ;参数2:下载后保存的文件名
                FileUtils.copyURLToFile(new URL(url), new File(name));
            } catch (IOException e)
            {
                e.printStackTrace();
                System.err.println("IO异常,downloader 方法出现问题");
            }
        }
    }
}

4、总结:三种创建方式的区别:

Thread、Runnable、Callable,都能用来开启多个线程来执行业务逻辑。

继承Thread 类 和 实现 Runnable接口的对比:

OOP 指的是面向对象编程(Object-Oriented Programming)
在这里插入图片描述


继承 Thread 类:(重写run()方法)
自定义线程子类A,继承 Thread 类,然后重写 run() 方法,把具体的业务逻辑写在run方法里面。
通过子类自身去调用 start() 方法,让 JVM 去开启一条新的线程去执行 run() 方法。

这样就可以启动多条线程。


实现 Runnable 接口:(实现 run() 方法)
自定义线程类B,实现 Runnable 接口,它启动多个线程,是通过 创建多个Thread 线程对象,然后把线程类B作为参数传给 Thread 线程对象,由Thread线程对象来调用 start 方法的


实现 Callable 接口:(实现 call() 方法)

自定义线程类C,实现 Callable 接口,它启动多个线程,是通过创建一个线程池,然后把线程类对象C作为任务参数提交到线程池,由线程池负责提供新线程来执行线程类对象C中定义的任务逻辑
线程类对象C中定义的任务逻辑,就是指重写 call() 方法里面的业务逻辑。


在这里插入图片描述



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

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

相关文章

【算法刷题day22】Leetcode:235. 二叉搜索树的最近公共祖先、701. 二叉搜索树中的插入操作、450. 删除二叉搜索树中的节点

文章目录 Leetcode 235. 二叉搜索树的最近公共祖先解题思路代码总结 Leetcode 701. 二叉搜索树中的插入操作解题思路代码总结 Leetcode 450. 删除二叉搜索树中的节点解题思路代码总结 草稿图网站 java的Deque Leetcode 235. 二叉搜索树的最近公共祖先 题目&#xff1a;235. 二…

代码随想录第36天 | 435. 无重叠区间 、 763.划分字母区间 、 56. 合并区间

一、前言&#xff1a; 参考文献&#xff1a;代码随想录 今天的主题是贪心算法中的重叠区间&#xff0c;就像昨天的扎气球问题&#xff0c;就是通过排序&#xff0c;然后将区间重叠起来&#xff0c;然后更具边界值判断这个区间是否重叠。 二、无重叠区间 1、思路&#xff1a…

异常处理过程和范例

目录 异常定义 异常关联 异常捕获与处理 查询 emp 数据表中工作岗位是 MANAGER 的员工信息&#xff0c;如果不存在这个员工&#xff0c;则输出“没有数据记录返回”&#xff0c;如果存在多个记录&#xff0c;则输出“返回数据记录超过一行” 更新数据表 emp 中部门编号&am…

产品推荐 | iWave 的 FPGA-IP 评估附加 FMC 卡

1、产品概述 iWave 的 FPGA-IP 评估附加 FMC 卡旨在满足 ANSI/VITA 57.1 FMC 标准。该卡支持高引脚数 &#xff08;HPC&#xff09; 和低引脚数 &#xff08;LPC&#xff09; 连接器&#xff0c;可在风冷环境中使用。FPGA-IP评估附加卡可以与市场上的大多数FPGA开发套件连接。…

LeetCode 994—— 腐烂的橘子

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 1.记录下初始新鲜橘子的位置到 notRotting&#xff0c;我们按照行把二维数组拉成一维&#xff0c;所以&#xff0c;一个vector 就可以实现了&#xff1b;2.如果没有新鲜橘子&#xff0c;那么第 0 分钟所有橘子已经…

44-技术演进(下):软件架构和应用生命周期技术演进之路

应用、系统资源、应用生命周期管理这 3 个维度&#xff0c;构成了我们对云的所有诉求。 我会介绍下应用维度和应用生命周期管理维度的技术演进。 我们就先来看下软件架构的演进之路。 软件架构的演进 软件架构技术演进如下图所示&#xff1a; 单体架构 在单体架构中&#xff…

浅聊java集合框架中的java.util.LinkedList

java集合框架总览 Java集合框架是一个用来代表和操纵集合的统一架构&#xff0c;它为管理和组织对象的集合提供了一组类和接口。这个框架包含三个主要部分&#xff1a;接口、实现和算法。 接口&#xff1a; Collection&#xff1a;这是集合框架的根接口&#xff0c;定义了集…

vue 上传视频

controlslist 属性可以用于告诉浏览器在视频播放过程中应该显示哪些默认的用户界面控件 代码&#xff1a; <template><div class"schematicDiagramIndex"><el-container><el-header v-if"this.radiooCar1"><el-button click&qu…

【精选】发布应用到应用商店的基本介绍

摘要 本文旨在介绍如何在各大应用商店发布应用&#xff0c;包括市场选择、准备材料、上架步骤以及常见被拒原因及解决方法。通过详细的步骤和经验分享&#xff0c;帮助开发者顺利将应用推向市场。 引言 随着移动应用市场的不断发展&#xff0c;越来越多的开发者希望将他们的…

如何关闭WordPress的自动更新功能

Wordpress为什么自动更新 WordPress自动更新是为了提供更好的安全性和稳定性。 安全性&#xff1a;WordPress是一个广泛使用的内容管理系统&#xff0c;因此成为恶意攻击的目标。WordPress的自动更新功能确保你的网站及时获得最新的安全补丁和修复程序&#xff0c;以保护你的网…

自动化测试selenium(1)

目录 什么是自动化测试 自动化测试 单元测试 接口测试 UI自动化测试 适合做自动化测试的项目 如何实施自动化测试 自动化测试需要了解的技能 selenium介绍 特性 原理 什么是自动化测试 自动化测试 自动化测试是指软件测试的自动化, 在预设状态下运行应用程序或者系…

标准 I/O 库

直接使用系统调用的缺点&#xff1a; (1) 影响系统性能 系统调用比普通函数调用开销大 因为&#xff0c;频繁的系统调用要进行用户空间和内核空间的切换 (2) 系统调用一次所能读写的数据量大小&#xff0c;受硬件的限制 解决方案&#xff1a;使用带缓冲功能的标准I/O库&#x…

RocketMQ笔记(七)SpringBoot整合RocketMQ发送事务消息

目录 一、简介1.1、流程图1.2、事务消息流程介绍 二、Maven依赖三、生产者3.1、application配置3.2、员工表3.3、实体3.4、持久层3.5、监听器 四、测试4.1、普通消息4.2、事务消息4.2.1、消费者4.2.2、正常提交4.2.3、异常提交 五、其他5.1、接口说明5.2、checkLocalTransactio…

智能传真机触摸屏中应用的触摸感应芯片

智能传真机是应用扫描和光电变换技术&#xff0c;把文件、图表、照片等静止图像转换成电信号&#xff0c;传送到接收端&#xff0c;以记录形式进行复制的通信设备。智能传真机将需发送的原件按照规定的顺序&#xff0c;通过光学扫描系统分解成许多微小单元&#xff08;称为像素…

AXS4110 单节锂电池保护芯片 爱协生 兼容XB6042/CM1124 低成本

概述 AXS4110系列产品是一种针对锂离子或聚合物电池保护的高集成解决方案芯片。AXS4110系列包含先进的功率MOSFET、高精度电压检测电路和延时电路。AXS4110系列采用DFN1x1x0.37_4封装&#xff0c;使其成为小体积电池保护的理想解决方案。 AXS4110具有过充、过放、过流、0V充电…

SpirngBoot开发常用知识

springboot开发常用知识 命令行打包SpringBoot打包插件window端口命令临时属性设置热部署启动热部署热部署范围 常用计量单位数据校验加载测试的专用属性Web环境模拟测试如何发送虚拟请求业务层测试回滚随机产生测试用例内置数据源 命令行打包 对SpringBoot项目进行打包命令行…

液冷是大模型对算力需求的必然选择?|英伟达 GTC 2024六大亮点

在这个以高性能计算和大模型推动未来通用人工智能时代&#xff0c;算力已成为科技发展的隐形支柱。本文将重点探讨算力的演进&#xff0c;深入分析在不同领域中算力如何成为推动进步的基石&#xff1b;着眼于液冷如何突破算力瓶颈成为引领未来的先锋&#xff0c;对液冷散热的三…

智慧城市中的物联网革命——青创智通

工业物联网解决方案-工业IOT-青创智通 得益于物联网 (IoT)的变革力量&#xff0c;智慧城市的概念正在迅速成为现实。物联网正在从根本上改变城市的运作方式&#xff0c;为城市居民带来更高的效率、可持续性和生活质量。在本文中&#xff0c;我们将探讨物联网在智慧城市中的作用…

小程序商城免费搭建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

面对DDOS攻击,有哪些解决办法

随着互联网带宽的持续增长以及DDOS黑客技术的发展&#xff0c;DDOS拒绝服务攻击的实施变得愈发容易。商业竞争、打击报复、网络敲诈等多种因素&#xff0c;各行各业的用户都曾受到DDOS攻击的威胁。 一旦遭受到DDOS攻击&#xff0c;随之而来的就是业务宕机&#xff0c;用户无法…