【昕宝爸爸小模块】浅谈之创建线程的几种方式

在这里插入图片描述

➡️博客首页       https://blog.csdn.net/Java_Yangxiaoyuan


       欢迎优秀的你👍点赞、🗂️收藏、加❤️关注哦。


       本文章CSDN首发,欢迎转载,要注明出处哦!


       先感谢优秀的你能认真的看完本文,有问题欢迎评论区交流,都会认真回复!


浅谈之创建线程的几种方式

  • 一、✅典型解析
    • 1.1✅Runnable和Callable区别
    • 1.2✅Future
    • 1.3✅FutureTask和Callable示例
  • 二、✅拓展知识仓
    • 2.1✅Runnable接口是什么
    • 2.2✅线程安全有哪些特性
    • 2.3✅什么是原子性
    • 2.4✅如何保证多线程同时操作数据不相互污染
    • 2.5✅Thread类有哪些构造函数
    • 2.6✅原子性和并行操作有什么关系
    • 2.7✅如何保证原子性操作不被干扰
    • 2.8✅线程安全和锁有啥区别
    • 2.9✅线程安全的优缺点是什么


一、✅典型解析


在Java中,共有四种方式可以创建线程,分别是:


  • 继承Thread类创建线程
  • 实现Runnable接门创建线程
  • 通过CallableFutureTask 创建线程
  • 通过线程池创建线程




    其实,归根结底最终就两种,一个是继承Thread类,一个是实现 Runnable接口 ,至于其他的。也是基于这两个方式实现的。但是有的时候面试官更关注的是实际写代码过程中,有几种方式可以实现所以一般说4种也没啥毛病。

1.1✅Runnable和Callable区别


Runnable接口Callable接口 都可以用来创建新线程,实现Runnable的时候,需要实现run方法;实现Callable接口的话,需要实现call方法


Runnable的run方法无返回值,Callable的call方法有返回值,类型为Object。


Callable中可以够抛出checked exception,而Runnable不可以。


CallableRunnable都可以应用于executors 。而 Thread类 只支持Runnable


1.2✅Future


Future是一个接口,代表了一个异步执行的结果。接口中的方法用来检查执行是否完成、等待完成和得到执行的结果。当执行完成后,只能通过get()方法得到结果,get方法会阻塞直到结果准备好了。如果想取消,那么调用cancel()方法


FutureTaskFuture接口的一个实现,它实现了一个可以提交给Executor执行的任务,并且可以用来检查任务的执行状态和获取任务的执行结果。


1.3✅FutureTask和Callable示例


import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
* @author xinbaobaba
* FutureTask和Callable示例
*/
public class FutureAndCallableExample {
	
	public static void main(Stringl] args) throws InterruptedException, ExecutionException {
		Callable<String> callable = () -> {
			System.out.println("Entered Callable");
			Thread.sleep(2000);
			return "Hello from Callable";
		});
	
		FutureTask<String> futureTask = new FutureTask<>(callable);
		Thread thread = new Thread(futureTask);
		thread.start();


		System.out.println("Do something else while callable is getting executed");
		System.out.println("Retrieved: " + futureTask.get());
	}
}

二、✅拓展知识仓


2.1✅Runnable接口是什么


Runnable接口是Java中用于定义线程任务的接口。在Java中,可以通过实现Runnable接口来定义线程任务,实现Runnable接口的类必须实现run()方法,该方法定义了线程要执行的具体操作。通过创建Runnable对象并将其传递给Thread类的构造函数,可以创建一个新的线程,并启动该线程执行任务。


一个简单的示例:

/**
* @author xinbaobaba
* 使用Java实现Runnable接口来创建线程
*/

public class MyRunnableTask implements Runnable {
    @Override
    public void run() {
        // 线程执行的代码
        System.out.println("Hello from the thread!");
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建Runnable对象
        MyRunnableTask task = new MyRunnableTask();
        
        // 创建Thread对象,并传递Runnable对象作为参数
        Thread thread = new Thread(task);
        
        // 启动线程
        thread.start();
    }
}

代码解析:定义了一个名为MyRunnableTask的类,它实现了Runnable接口并重写了run()方法。在run()方法中,我们简单地打印了一条消息。然后,在main()方法中,我们创建了MyRunnableTask的实例,并使用该实例创建了一个新的线程对象。最后,我们调用start()方法启动了线程。当线程启动后,它将自动执行我们在run()方法中定义的代码。


2.2✅线程安全有哪些特性


线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。


线程安全的特性主要有以下几个方面


  1. 原子性:一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。原子性可以确保多个线程之间的操作不会相互干扰,从而保证数据的一致性。
  2. 可见性:一个线程对主内存的修改可以及时的被其他线程所观察到。可见性可以保证多个线程之间共享数据的实时更新,确保每个线程都能获取到最新的数据状态。
  3. 有序性:一个线程观察其他线程的指令执行顺序,由于指令重排序的存在,该观察结果一般杂乱无序。有序性可以保证代码的执行顺序按照程序员的预期进行,避免出现意外的结果。

以上就是线程安全的三大特性:原子性、可见性和有序性。这些特性可以确保多线程程序在并发执行时能够正确地处理共享数据,避免出现数据不一致、数据污染等问题

以下是一个简单的示例:



/**
* @author xinbaobaba
* 线程安全的基本特性ceshidemo
*/
public class ThreadSafeCounter {
    private int count = 0;

    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

public class CounterThread extends Thread {
    private ThreadSafeCounter counter;

    public CounterThread(ThreadSafeCounter counter) {
        this.counter = counter;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.increment();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ThreadSafeCounter counter = new ThreadSafeCounter();
        CounterThread thread1 = new CounterThread(counter);
        CounterThread thread2 = new CounterThread(counter);
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Final count: " + counter.getCount());
    }
}

代码解析:定义了一个ThreadSafeCounter类,它有一个共享的count变量,用于计数。我们还定义了一个CounterThread类,它继承了Thread类,用于创建新的线程。每个线程都会执行1000次increment()操作,即增加计数。在main()方法中,我们创建了两个CounterThread线程,并启动它们。最后,我们等待两个线程执行完毕,并打印出最终的计数结果。


示例演示了线程安全的基本特性:原子性、可见性和有序性。由于increment()操作是原子的,即不会被其他线程打断,因此最终的计数结果是正确的。由于count变量的可见性得到了保证,每个线程都能观察到最新的计数结果。此外,由于线程调度和指令重排序的原因,最终的计数结果可能会与预期的顺序不同,但最终的结果仍然是正确的。


2.3✅什么是原子性


原子性是指在计算机科学中,一个操作(或一组操作)不可被中断地执行完毕或不执行,具有原子性的操作不会受到其他并发操作的干扰,能够保证数据的一致性和正确性。通俗来说,原子性就是“一气呵成”,不可分割的意思。原子性确保多个操作是一个不可以分割的整体,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行。在数据库事务中,原子性是非常重要的特性之一,它可以确保事务中的所有操作都被完整地执行或者都不被执行,从而保持数据的一致性。


2.4✅如何保证多线程同时操作数据不相互污染


要保证多线程同时操作数据不相互污染,可以采用以下几种方法


1. 使用锁机制:可以使用Java中的synchronized关键字或者Lock对象来实现对共享数据的同步访问,确保一次只有一个线程能够访问共享数据,避免多个线程同时操作数据导致数据污染。


2. 使用读写锁:读写锁允许多个线程同时读取共享数据,但在写入数据时只允许一个线程访问,这样可以提高并发性能。


3. 使用volatile关键字:volatile关键字可以确保共享数据的可见性,当一个线程修改了共享数据后,其他线程可以立即看到修改后的数据。


4. 使用事务:数据库事务可以确保一系列操作要么全部成功,要么全部失败回滚,从而避免数据的不一致性。在Java中,可以使用JDBC或者ORM框架(如Hibernate)来管理数据库事务。


5. 使用线程安全的数据结构:Java提供了很多线程安全的数据结构,如Vector、Hashtable、CopyOnWriteArrayList等,这些数据结构内部已经实现了同步机制,可以保证多个线程同时访问时的正确性。


6. 避免共享状态:尽可能地减少共享状态,让每个线程都有自己的数据副本,这样可以避免多个线程之间的数据竞争和相互污染。


7. 使用消息队列:通过消息队列可以将多个线程之间的通信解耦,每个线程将需要操作的数据发送到队列中,另一个线程从队列中获取数据进行处理,这样可以避免直接访问共享数据。


为了保证多线程同时操作数据不相互污染,可以采用多种方法来保证数据的原子性、可见性和有序性。在具体实现时,需要根据实际情况选择适合的方法来保证数据的正确性和一致性


代码示例:


/**
* @author xinbaobaba
* 如何使用synchronized关键字来保证多线程同时操作数据不相互污染
*/
public class SharedData {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

public class ThreadA extends Thread {
    private final SharedData sharedData;

    public ThreadA(SharedData sharedData) {
        this.sharedData = sharedData;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            sharedData.increment();
        }
    }
}

public class ThreadB extends Thread {
    private final SharedData sharedData;

    public ThreadB(SharedData sharedData) {
        this.sharedData = sharedData;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(sharedData.getCount());
        }
    }
}

public class Main {
    public static void main(String[] args) {
        SharedData sharedData = new SharedData();
        ThreadA threadA = new ThreadA(sharedData);
        ThreadB threadB = new ThreadB(sharedData);
        threadA.start();
        threadB.start();
        try {
            threadA.join();
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

代码解析:定义了一个SharedData类,它有一个共享的count变量,用于计数。我们还定义了两个线程类ThreadAThreadB,它们分别执行增加计数和获取计数的操作。在SharedData类中,我们使用synchronized关键字对increment()getCount()方法进行了同步,确保一次只有一个线程能够访问共享数据。在main()方法中,我们创建了两个线程对象,并启动它们。由于使用了同步机制,即使两个线程同时访问共享数据,也不会出现数据污染的问题。最终的计数结果将正确地累加并输出。


2.5✅Thread类有哪些构造函数


在Java中,Thread类有几个构造函数,它们允许你创建和初始化线程。以下是Thread类的构造函数:


  1. Thread():这是一个默认构造函数,用于创建一个新的线程对象,但不会自动启动线程。
  2. Thread(Runnable target):这个构造函数接受一个实现了Runnable接口的对象作为参数,该对象定义了线程要执行的代码。
  3. Thread(ThreadGroup group, Runnable target):这个构造函数接受一个ThreadGroup对象和一个实现了Runnable接口的对象作为参数。ThreadGroup对象定义了线程所属的线程组。
  4. Thread(String name):这个构造函数接受一个字符串作为参数,用于为线程设置一个名称。
  5. Thread(ThreadGroup group, String name):这个构造函数接受一个ThreadGroup对象和一个字符串作为参数。ThreadGroup对象定义了线程所属的线程组,字符串用于为线程设置一个名称。
  6. Thread(Runnable target, String name):这个构造函数接受一个实现了Runnable接口的对象和一个字符串作为参数。字符串用于为线程设置一个名称,而Runnable对象定义了线程要执行的代码。
  7. Thread(ThreadGroup group, Runnable target, String name):这个构造函数接受一个ThreadGroup对象、一个实现了Runnable接口的对象和一个字符串作为参数。这些参数允许你设置线程的名称、定义线程要执行的代码以及设置线程所属的线程组。

注意:当你使用这些构造函数创建线程时,它们只是创建了线程对象,并不会自动启动线程。要启动线程,你需要调用线程对象的start()方法。


2.6✅原子性和并行操作有什么关系


原子性和并行操作是计算机科学中的两个重要概念,它们之间存在一定的关系。


原子性是指一个操作或者一组操作不可分割地执行,要么全部执行成功,要么全部执行失败。原子性主要应用于多线程编程和数据库事务管理中,用于保证多个线程或者事务中的操作的一致性和正确性。在多线程编程中,原子性可以避免多个线程同时访问共享数据时出现数据竞争和不一致的问题。在数据库事务管理中,原子性可以保证一系列操作要么全部成功,要么全部失败回滚,从而保持数据的一致性。


并行操作是指多个操作同时执行,以提高程序的执行效率。并行操作通常应用于多核处理器和分布式计算中,通过将多个任务分配给多个处理器或者计算机节点,同时执行这些任务,可以加快程序的执行速度。


原子性和并行操作之间存在一定的关系。在并行操作中,为了保持数据的一致性和正确性,需要确保每个操作都是原子的,即不可分割地执行。同时,原子性也可以帮助避免并行操作中可能出现的数据竞争和不一致问题。在实现并行操作时,可以通过加锁、事务管理等方式来保证操作的原子性,从而保证数据的一致性和正确性。


注意:原子性和并行操作之间存在一定的矛盾和权衡。过于强调原子性可能会影响并行操作的效率,而过于强调并行操作可能会增加数据竞争和不一致的风险。因此,在实际应用中,需要根据具体场景和需求来平衡原子性和并行操作的关系,以实现最佳的性能和正确性。


代码的示例:


/**
* @author xinbaobaba
* 原子性和并行操作之间的关系示例
*/
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicityAndParallelism {
    public static void main(String[] args) {
        AtomicInteger atomicCounter = new AtomicInteger(0);
        int numThreads = 10;
        Thread[] threads = new Thread[numThreads];

        // 创建并启动多个线程,每个线程递增计数器
        for (int i = 0; i < numThreads; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    atomicCounter.incrementAndGet(); // 原子性操作
                }
            });
            threads[i].start();
        }

        // 等待所有线程执行完毕
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 输出最终的计数器值,应该等于线程数量乘以每个线程的递增值
        System.out.println("Final counter value: " + atomicCounter.get());
    }
}

代码解析:使用了AtomicInteger类来创建一个原子性计数器。AtomicInteger类中的incrementAndGet()方法是一个原子性操作,它可以保证在多线程环境下对计数器的递增操作是原子的,即不可分割地执行。这样可以避免多个线程同时访问计数器时出现数据竞争和不一致的问题。


我们创建了10个线程,每个线程都执行1000次计数器的递增操作。通过使用原子性计数器,我们可以确保最终的计数器值是正确的,即等于线程数量乘以每个线程的递增值。如果没有原子性保证,可能会出现数据竞争和不一致的问题,导致最终的计数器值不正确。


示例说明了原子性和并行操作之间的关系。在并行操作中,原子性可以保证多个操作的一致性和正确性,避免数据竞争和不一致的问题。同时,通过并行操作可以提高程序的执行效率。在实际应用中,需要根据具体场景和需求来平衡原子性和并行操作的关系,以实现最佳的性能和正确性。


2.7✅如何保证原子性操作不被干扰


要保证原子性操作不被干扰,可以采用以下几种方法:


  1. 使用锁机制:Java中的synchronized关键字或者Lock接口可以用来控制对共享资源的访问,确保一次只有一个线程能够执行某个代码块或方法,从而防止其他线程的干扰。
  2. 使用并发容器:Java提供了很多并发容器,如ConcurrentHashMap、CopyOnWriteArrayList等,这些容器内部已经实现了线程安全,可以避免多线程环境下的数据不一致问题。
  3. 使用事务:在数据库操作中,可以使用事务来保证原子性。事务是一系列的操作,要么全部成功,要么全部失败回滚,这样可以避免数据的不一致。
  4. 使用乐观锁或悲观锁:在并发控制中,乐观锁和悲观锁也是常用的手段。乐观锁基于数据版本记录机制,通过版本号或时间戳等方式来控制并发操作时的数据一致性;悲观锁则是通过数据库的行级锁或表级锁来限制并发操作。
  5. 避免共享状态:尽可能地减少共享状态,每个线程处理自己的数据副本,不与其他线程共享数据。这样自然就不存在数据不一致的问题。
  6. 使用无锁数据结构:无锁数据结构(Lock-free data structures)是另一种解决方案,它使用原子操作来更新数据,而不需要显式的锁机制。
  7. 避免长时间持有锁:尽量减少持有锁的时间,以减少其他线程的等待时间,提高并发性能。
  8. 使用分布式系统解决方案:对于大规模的分布式系统,可以考虑使用分布式事务、两阶段提交、三阶段提交等解决方案来保证操作的原子性。

总之,要保证原子性操作不被干扰,需要结合具体的应用场景和需求,选择合适的并发控制策略和工具。


2.8✅线程安全和锁有啥区别


线程安全是多线程编程中使用的概念,用于保证多个线程之间数据的安全性和一致性。线程安全涉及到多个线程对共享数据的访问和修改,需要采取措施来避免数据竞争和不一致的问题。而锁是实现线程安全的一种机制,它可以控制对共享资源的访问,确保一次只有一个线程能够执行某个代码块或方法,从而防止其他线程的干扰。锁机制包括synchronized关键字、Lock接口、乐观锁和悲观锁等。因此,线程安全是一个更广泛的概念,而锁是实现线程安全的一种具体手段。


2.9✅线程安全的优缺点是什么


线程安全的优点主要包括:


  1. 保证数据完整性:线程安全可以保证多线程环境下的数据完整性和一致性,避免数据竞争和不一致的问题。
  2. 提高系统稳定性:线程安全有助于提高系统的稳定性和可靠性,减少因数据错误或不一致导致的问题。
  3. 充分利用多核资源:线程安全可以利用多核处理器的资源,通过并行计算提高程序的执行效率。

线程安全缺点


  1. 性能开销:线程安全的实现需要引入额外的机制来控制线程的访问和同步,这可能导致一定的性能开销。
  2. 编程难度增加:线程安全的实现需要更全面深入地考虑多线程的同步和协调问题,增加了编程的复杂度和难度。
  3. 死锁和活锁风险:线程安全需要合理地设计锁机制和控制线程的执行顺序,否则可能导致死锁或活锁的问题。
  4. 资源竞争:在多线程环境下,资源竞争可能导致线程阻塞或等待,影响程序的执行效率和响应性。

因此,在实现线程安全时需要权衡利弊,根据具体的应用场景和需求选择合适的线程安全策略,以实现最佳的性能和正确性。


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

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

相关文章

开源鸿蒙适配芯片到底都做了哪些工作?

随着智能设备市场的不断扩大和技术的进步&#xff0c;鸿蒙操作系统成为了备受瞩目的开源项目。作为一个全场景智能生态的基础&#xff0c;鸿蒙不仅仅是一个操作系统&#xff0c;还涉及到硬件层面的适配。然而&#xff0c;开源鸿蒙芯片适配并非易事&#xff0c;面临着一些难点和…

国内外好用的 LLM 列表

视频来源&#xff1a;https://www.bilibili.com/video/BV1c64y157Qm/?vd_source1e841703c91b5b77fd20e5707bae49d2 下图是测试括号闭合能力的得分

PointMixer: MLP-Mixer for Point Cloud Understanding

Abstract MLP-Mixer 最近崭露头角,成为对抗CNNs和Transformer领域的新挑战者。尽管相比Transformer更为简单,但通道混合MLPs和令牌混合MLPs的概念在图像识别任务中取得了显著的性能。与图像不同,点云本质上是稀疏、无序和不规则的,这限制了直接将MLP-Mixer用于点云理解。为…

推荐系统模型(一) DFN 详解 Deep Feedback Network for Recommendation

背景 在大多数的推荐系统中&#xff0c;往往注重于隐式正反馈(例如&#xff1a;点击)&#xff0c;而忽略掉用户的其他行为(例如大多数CTR模型只考虑用户的喜欢&#xff0c;而忽略了不喜欢)。腾讯在Deep Feedback Network for Recommendation 一文中&#xff0c;提出了一个新颖…

鸿蒙开发工程师会不会有很好的就业前景?

一&#xff0c;鸿蒙带动IT开发和应用整体结构的变革 1月11日&#xff0c;以鸿蒙为首的华为概念股大幅走强&#xff0c;创业板创识科技拉升封板&#xff0c;传智教育、智度股份、高新发展、立达信、吉大正元等多股涨停&#xff0c;华亚电子、九联科技、软通动力、辰奕智能、芯海…

【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(排查问题指令 - 下)

带你一同学习和实践操作Linux服务器必学的Shell指令 前提介绍more和less命令用法more命令命令格式命令参数 常用操作命令案例分析显示文件中从第3行起的内容将日志内容设置为每屏显示4行快速定位和显示文件中包含特定字符串结合管道和more命令来分页显示 less指令命令格式搜索指…

DataFunSummit:2023年云原生大数据峰会:核心内容与学习收获(附大会核心PPT下载)

随着数字化转型的深入推进&#xff0c;大数据技术已经成为企业获取竞争优势的关键因素之一。本次峰会汇聚了业界顶尖的大数据专家、企业领袖和技术精英&#xff0c;共同探讨云原生大数据领域的最新技术和趋势。本文将深入分析峰会的核心内容&#xff0c;并探讨参会者从中能学到…

大数据之谷歌文件系统论文 GFS The Google File System

原文地址 谷歌文件系统论文 摘要 我们设计并实现了Google文件系统&#xff0c;这是一个面向大规模分布式数据密集型应用的可扩展分布式文件系统。 它在廉价的通用硬件上运行&#xff0c;提供了容错性&#xff0c;并向大量客户端提供高聚合性能。 尽管与先前的分布式文件系统…

vue知识-07

ref # 放在组件上&#xff1a; this.$refs.名字 ---组件对象.组件对象.属性 # 在vue项目中使用: // 写在组件上 <HelloWorld ref"my_hello_world"></HelloWorld>handleClick() {console.log(this.$refs)this.$refs.my_hello_world.name # 获取子组件中…

CSS3十大滤镜效果详解

滤镜效果 类似于美颜相机、美图秀秀这样的美颜工具&#xff0c;能够让我们轻松地应用多种特效&#xff0c;例如转换为黑白照片、复古风格化、调整亮度等。在之前仅凭CSS几乎很难做到这些效果。 但在CSS3的语法中&#xff0c;所有的这些视觉特效都是通过“filter”属性来快速实…

基于Java+SSM的技术的社区人口管理系统详细设计和实现【附源码】

基于JavaSSM的技术的社区人口管理系统详细设计和实现 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 …

备份和容灾讲解

备份和容灾 &#xff08;1&#xff09;容灾&#xff08;容许灾难的发生&#xff09;是一种架构方案&#xff0c;包括了很多方案&#xff0c;如下 本地高可用 双活&#xff08;特指存储&#xff0c;可以理解为两端同时对外提供服务&#xff09;&#xff1a;通过一个双写模块把…

【代码随想录06】454. 四数相加 II 383. 赎金信 15. 三数之和 18. 四数之和

目录 454. 四数相加 II题目描述做题思路参考代码 383. 赎金信题目描述做题思路参考代码 15. 三数之和题目描述参考代码 18. 四数之和题目描述参考代码 454. 四数相加 II 题目描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你…

burp靶场——XXE注入

XML 外部实体 (XXE) 注入 1. 什么是xxe漏洞&#xff1a; https://portswigger.net/web-security/xxe#what-is-xml-external-entity-injection XML 外部实体注入&#xff08;也称为 XXE&#xff09;是一种 Web 安全漏洞&#xff0c;允许攻击者干扰应用程序对 XML 数据的处理。…

Go语言认识

Go语言认识 1. Go语言的设计背景2. Go语言的历程3. Go语言对比分析4. Go语言未来的发展规划5. 要不要选择Go 关注 go博客 直接了解第一手资料。 go文档 了解go的全貌。 1. Go语言的设计背景 Go语言&#xff08;也称为Golang&#xff09;是由Google开发的一种编程语言。它的设计…

59.说一下 spring 的事务隔离?

spring 的事务隔离有什么作用? 用来解决并发事务所产生一些问题,并发会产生什么问题? 1.脏读2.不可重复度3.幻影读事务隔离的概念 通过设置隔离级别可解决在并发过程中产生的那些问题分别举例说明 1.脏读 上述图表示:一个事务,读取了另一个事务中没有提交的数据,会在…

LabVIEW高效振动时效处理系统

概述&#xff1a;介绍了一个利用LabVIEW开发的振动时效处理系统&#xff0c;有效降低加工工件的内部残余应力&#xff0c;提升其质量和寿命。 项目背景 工业加工中的工件常存在残余应力问题&#xff0c;这直接影响工件的质量和寿命。虽然热时效和自然时效法被广泛应用于降低残余…

数据结构学习 jz45 把数组排成最小的数

关键词&#xff1a;贪心 排序 快速排序 题目&#xff1a;破解闯关密码 思路&#xff1a; 快排自己制定快排规则 开辟一个vector存string&#xff0c;自己制定排序规则&#xff0c;然后用快排比较string大小。 排序规则&#xff1a; sort(strs.begin(),strs.end(),[](string…

供应链管理是什么?专业就业前景如何?

什么是供应链管理 供应链&#xff08;Supply Chain&#xff09;&#xff0c;也被称为价值链或需求链&#xff08;Demand Chain&#xff09;&#xff0c;包括顾客、供应商、过程、产品以及对产品和服务有影响的各种资源。供应链强调的是公司之间的过程与关系。 《中华人民共和国…

置位复位寄存器的某一位(多工位多工站渗透线控制应用)

这里的置位复位特定寄存器位功能块可以应用在渗透线控制应用上,我们可以根据小车当前所在位置,对相关工作槽里的标志位进行置位复位等操作(某个槽有产品,某个槽没有产品等)。 下面我们看下对应的控制要求 1、置位复位特定的位 2、置位复位寄存器中的某一位 3、置位bit8 4…