Java多线程基础知识(超详细)

Java多线程基础知识

什么是多线程

在Java中,多线程(Multithreading)是并发编程的一种形式,它允许在一个程序中同时运行多个线程。每个线程都是程序的一个独立执行流,拥有自己的堆栈和程序计数器,但共享程序的其他部分(如内存和静态变量)。

以下是多线程的几个关键概念:

  1. 线程:线程是程序执行流的最小单元。Java虚拟机(JVM)允许一个进程并发地执行多个线程。
  2. 并发:并发意味着多个线程在同一时间段内执行。然而,由于CPU资源有限,实际上同一时刻只有一个线程在执行,但线程的切换速度非常快,使得多个线程看起来像是在同时执行。
  3. 并行:并行是并发的特例,当多个线程在同一时刻(在不同的CPU或处理器核心上)同时执行时,称为并行。
  4. 线程状态:Java中的线程具有多种状态,包括新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。
  5. 线程同步:由于多个线程共享程序的资源,因此需要对这些资源进行同步以防止数据不一致或冲突。Java提供了多种同步机制,如synchronized关键字、Lock接口和相关的类(如ReentrantLock)、volatile关键字和原子类(如AtomicInteger)等。
  6. 线程安全:线程安全意味着多个线程在并发执行时能够正确地访问共享资源,而不会导致数据不一致或其他问题。编写线程安全的代码是并发编程中的一项重要挑战。
  7. 线程池:线程池是一种用于管理和复用线程的机制。通过线程池,可以减少线程的创建和销毁开销,提高程序的性能。Java提供了几种线程池实现,如FixedThreadPool、CachedThreadPool和ScheduledThreadPool等。

在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。然后,可以使用Thread类的start()方法启动线程。此外,Java还提供了丰富的并发工具类库,如java.util.concurrent包中的类,以支持更复杂的并发编程需求。

第一种实现方式

package com.mohuanan.test01;public class Test01 {public static void main(String[] args) {/*** 多线程的第一种实现方式:*      继承Thread*      重写run方法*      创建子类的对象**/MyThread mt1 = new MyThread();MyThread mt2 = new MyThread();mt1.setName("线程一");mt2.setName("线程二");//开启线程mt1.start();mt2.start();}
}

第二种实现方式

package com.mohuanan.test02;public class Test02 {public static void main(String[] args) {/** 多线程的第二种实现方式* 实现Runnable接口* 重写Run方法* 创建实现Runnable接口的类的对象* 创建Thread对象* 开启线程* */MyRun mr = new MyRun();Thread t1 = new Thread(mr);Thread t2 = new Thread(mr);t1.setName("线程1");t2.setName("线程2");//开启线程t1.start();t2.start();}
}

第三种实现方式

package com.mohuanan.test03;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;public class Test01 {public static void main(String[] args) throws ExecutionException, InterruptedException {/** 第三种实现方式:*       带有返回值*       实现Callable接口*       重写里面的call方法**       创建实现Callable接口的类的对象(表示进程要执行的任务)*       创建FutureTask对象(管理多线程运行的结果)*       创建Thread对象 并开启线程(表示线程)** */MyCallable mc = new MyCallable();FutureTask ft = new FutureTask(mc);Thread t = new Thread(ft);//开启进程t.start();//获取进程的返回值Integer sum = (Integer) ft.get();System.out.println(sum);}
}

在Java多线程里面常见的成员方法

在Java多线程编程中,Thread 类和其他相关类(如 RunnableExecutorServiceFuture 等)提供了许多用于管理和控制线程的成员方法。以下是一些在Java多线程编程中常见的成员方法:

  1. Thread类的方法
  • start(): 启动一个新线程并执行此线程中的 run() 方法。
  • run(): 如果此线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
  • currentThread(): 返回对当前正在执行的线程对象的引用。
  • interrupt(): 中断此线程。除非此线程当前正在等待、睡眠或以其他方式被阻塞,否则该线程将不会受到中断的影响。
  • isInterrupted(): 测试此线程是否已被中断。线程的中断状态由 interrupt() 方法设置。
  • sleep(long millis): 使当前正在执行的线程在指定的毫秒数内处于休眠(暂停执行)状态。
  • join(): 等待该线程终止。
  • setPriority(int newPriority): 更改此线程的优先级。
  • getPriority(): 返回此线程的优先级。
  • setDaemon(boolean on): 将此线程标记为守护线程或用户线程。
  • isDaemon(): 测试此线程是否为守护线程。
  • getState(): 返回此线程的状态。
  • yield(): 暂停当前正在执行的线程对象,并执行其他线程。
  • stop(): 已废弃。停止此线程的执行。此方法会引发 ThreadDeath 异常。
  • resume(): 已废弃。恢复此线程的执行。
  • suspend(): 已废弃。暂停此线程的执行。
  1. Runnable接口的方法
  • run(): 由线程执行的方法。实现此接口的类必须定义此未指定的方法。
  1. ExecutorService接口的方法(常用于线程池):
  • submit(Runnable task): 提交一个 Runnable 任务用于执行,并返回一个表示该任务的未来结果的 Future
  • submit(Callable<T> task): 提交一个 Callable 任务用于执行,并返回一个表示该任务的未来结果的 Future
  • shutdown(): 启动此执行程序的有序关闭序列,在此序列中,先前提交的任务将被执行,但不会接受新任务。
  • shutdownNow(): 试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
  • execute(Runnable command): 在未来某个时间点为给定命令执行一个任务。
  • awaitTermination(long timeout, TimeUnit unit): 如果此执行程序在此给定的超时时间之前终止,则返回 true(以及如果已终止则为 true)。
  • isTerminated(): 如果所有任务都已完成执行,则返回 true
  • isShutdown(): 如果此执行程序已关闭,则返回 true
  1. Future接口的方法(常与 ExecutorService 一起使用):
  • get(): 如有必要,等待计算完成,然后检索其结果。
  • get(long timeout, TimeUnit unit): 如有必要,最多等待给定的时间以获取结果(如果可用)。
  • cancel(boolean mayInterruptIfRunning): 尝试取消此任务的执行。
  • isDone(): 如果任务已完成,则返回 true
  • isCancelled(): 如果任务在完成前被取消,则返回 true

这些只是Java多线程编程中常见的一部分方法。根据具体的需求和场景,可能会使用到更多的方法和类。

同步代码块

在Java中,多线程同步代码块是一种确保在某一时刻只有一个线程能够执行某段代码的机制。这通常用于保护共享资源,避免数据不一致或脏读等问题。

同步代码块是什么?

同步代码块是Java中使用synchronized关键字来定义的代码块。当一个线程进入同步代码块时,它会获取一个锁(通常是该同步代码块所在对象的锁),然后执行代码块中的代码。在此期间,其他尝试进入该同步代码块的线程将被阻塞,直到第一个线程释放锁。

同步代码块有什么用?

同步代码块的主要用途是确保多线程环境下共享资源的访问是同步的,从而防止竞态条件(race condition)和数据不一致。

如何使用同步代码块?

同步代码块的基本语法如下:

synchronized (object) {// 需要同步的代码
}

其中,object是用作锁的任意对象。线程在进入同步代码块时会尝试获取该对象的锁,如果锁已经被其他线程持有,则该线程将被阻塞。

注意事项:

  1. 死锁:如果两个或多个线程相互等待对方释放资源,就会发生死锁。这可能导致应用程序停止响应。避免死锁的一个好方法是始终按照相同的顺序获取锁。
  2. 性能:同步代码块会引入额外的开销,因为线程在尝试获取锁时可能会被阻塞。因此,应该尽可能减少同步代码块的范围,只包含确实需要同步的代码。
  3. 避免过度同步:过度同步可能导致性能下降,甚至可能导致死锁。应该仔细分析代码,确定哪些部分需要同步,哪些部分可以安全地并行执行。
  4. 锁的粒度:锁的粒度越细,并发性能就越好,但编程复杂度也会增加。需要根据具体情况权衡。
  5. 选择正确的锁对象:同步代码块使用的锁对象应该能够唯一标识需要同步的资源。通常,可以使用共享资源的实例或类对象作为锁。
  6. 避免在同步代码块中调用可能阻塞的方法:如果在同步代码块中调用了一个可能会阻塞的方法(如I/O操作或等待用户输入),那么持有锁的线程可能会被阻塞很长时间,从而导致其他需要访问该资源的线程也被阻塞。这可能会导致性能下降或甚至死锁。
  7. 注意异常处理:在同步代码块中抛出异常时,需要确保锁能够被正确释放。否则,可能会导致其他线程永远无法获取锁。一种常见的做法是在finally块中释放锁,但请注意,在Java中,同步代码块在退出时会自动释放锁,所以你通常不需要在finally块中显式释放锁。

死锁

在Java中,死锁是指两个或多个线程在互相请求对方占用的资源时处于等待状态,导致程序无法继续执行的现象。具体来说,每个线程都持有一个资源并且同时等待另一个资源,形成一种僵局,没有任何一个线程能够释放其持有的资源,也无法获得它所需的资源。

以下是关于Java死锁的一些注意事项:

  1. 死锁的必要条件:死锁的发生通常需要满足以下四个条件,也被称为死锁的必要条件:
  • 互斥条件:至少有一个资源在任意时刻只能被一个线程占用。
  • 保持和等待条件:一个线程至少持有一个资源,并等待获取一个当前被其他线程持有的资源。
  • 不可剥夺条件:资源只能由持有它的线程释放,资源不可以被剥夺。
  • 循环等待条件:存在一个等待资源的循环,即每个线程都在等待下一个线程释放资源。

为了避免Java中的死锁,可以采取以下策略:

  1. 避免嵌套锁:尽量避免一个线程在持有一个锁的同时去请求另一个锁。如果确实需要获取多个锁,应该确保所有线程以相同的顺序请求和释放锁。
  2. 使用定时锁:使用tryLock()方法来尝试获取锁,并设置一个超时时间。如果超时时间内没有获取到锁,那么就放弃获取锁,并做一些其他的处理,比如重试或者返回错误。
  3. 锁分割:将大的锁分割成几个小的锁,使得不同的线程可以同时访问不同的资源。
  4. 检测死锁:使用工具或JVM内置功能(如JConsole)来监控和检测系统中的死锁,然后进行相应的处理。
  5. 资源分配策略:设计合理的资源分配策略,确保线程在请求资源时不会形成循环等待的情况。

总之,死锁是Java多线程编程中需要特别注意的问题。为了避免死锁的发生,需要深入理解死锁的原理和必要条件,并采取相应的策略来预防和处理死锁。

等待唤醒机制

在Java中,等待唤醒机制是线程间通信的一种重要手段,它允许一个线程等待某个条件成立,而另一个线程可以通知等待的线程该条件已经成立。等待唤醒机制主要依赖于wait()notify()/notifyAll()这几个方法。

使用方法:

  1. wait() 方法
  • 当线程调用某个对象的wait()方法时,它会释放该对象的锁,并进入等待状态,直到其他线程调用该对象的notify()notifyAll()方法。
  • wait()方法只能在同步方法或同步块中调用,否则会抛出IllegalMonitorStateException异常。
  1. notify() 方法
  • 当线程调用某个对象的notify()方法时,它会唤醒在该对象上等待的单个线程(如果有的话)。
  • notify()方法也必须在同步方法或同步块中调用,否则会抛出IllegalMonitorStateException异常。
  1. notifyAll() 方法
  • 当线程调用某个对象的notifyAll()方法时,它会唤醒在该对象上等待的所有线程。
  • 同样,notifyAll()方法也必须在同步方法或同步块中调用。

注意事项:

  1. 必须在同步块或同步方法中调用wait()notify()notifyAll()方法必须在同步块或同步方法中调用,因为它们是用于操作对象锁的。
  2. 释放锁:当线程调用wait()方法时,它会释放当前持有的锁,并进入等待状态。这使得其他线程有机会获取该锁并执行。
  3. 唤醒机制notify()方法只会唤醒等待队列中的一个线程(如果有的话),而notifyAll()方法会唤醒等待队列中的所有线程。但是,这并不意味着被唤醒的线程会立即执行,它们需要等待重新获取锁。
  4. 虚假唤醒:即使没有线程调用notify()notifyAll()方法,等待的线程也可能被唤醒(这被称为虚假唤醒)。因此,在wait()方法后,应该使用一个循环来检查条件是否真正满足。
  5. 异常处理wait()方法可能会抛出InterruptedException异常,因此在使用时需要处理这个异常。通常的做法是捕获该异常并重新等待,或者根据具体情况进行其他处理。
  6. 避免死锁:虽然等待唤醒机制本身不会导致死锁,但在多线程编程中仍然需要注意避免死锁的发生。例如,确保线程在获取多个锁时以相同的顺序进行,或者使用其他避免死锁的策略。

例子代码1

package com.mohuanan.test06;public class Desk {//总个数public static int count = 10;//食物状态//  0没有食物//  1有食物public static int foodFlag = 0;//锁对象 唯一public static Object lock = new Object();
}package com.mohuanan.test06;public class Cook extends Thread{@Overridepublic void run() {while(true){synchronized (Desk.lock){//判断共享数据是否到了末尾if(Desk.count==0){//到了末尾break;}else{//没有到末尾//判断桌子上有没有面条if(Desk.foodFlag ==0){//没有面条System.out.println("厨师正在制作面条");Desk.foodFlag = 1;//唤醒吃货Desk.lock.notifyAll();}else{//有面条try {Desk.lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}}
package com.mohuanan.test06;public class Foodie extends Thread {//多线程的四部走/** 1. 循环* 2. 同步代码块(锁)* 3. 判断共享数据是否到了末尾(到了末尾)* 4. 判断共享数据是否到了末尾(没有到末尾,执行核心逻辑)* */@Overridepublic void run() {while (true) {synchronized (Desk.lock) {if (Desk.count == 0) {//共享数据到了末尾 退出break;} else {//共享数据没有到达末尾//判断桌子上有没有食物if (Desk.foodFlag == 0) {//没有食物 等待try {Desk.lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{//有食物Desk.count--;System.out.println("吃货正在吃第"+Desk.count+"碗面条");//修改桌子上食物的状态Desk.foodFlag = 0;//唤醒厨师继续做面条Desk.lock.notifyAll();}}}}}
}package com.mohuanan.test06;public class ThreadDemo {public static void main(String[] args) {//创建线程的对象Cook c = new Cook();Foodie f = new Foodie();//给线程设置名字c.setName("厨师");f.setName("吃货");//开启线程c.start();f.start();}
}

例子代码2

package com.mohuanan.test07;import java.util.concurrent.ArrayBlockingQueue;public class Cook extends Thread{ArrayBlockingQueue<String> abq;public Cook(ArrayBlockingQueue<String> abq) {this.abq = abq;}@Overridepublic void run() {while(true){//不断往队列里面放面条try {//put 和 take方法在Java中源代码里面是有锁的 所以不用再自己写锁abq.put("面条");System.out.println("放了一碗面条");} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
package com.mohuanan.test07;import java.util.concurrent.ArrayBlockingQueue;public class Foodie extends Thread{ArrayBlockingQueue<String> abq;public Foodie(ArrayBlockingQueue<String> abq) {this.abq = abq;}@Overridepublic void run() {while (true){//不断的从队列里面获取食物try {String food = abq.take();System.out.println(food);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
package com.mohuanan.test07;import java.util.concurrent.ArrayBlockingQueue;public class Test {public static void main(String[] args) {//创建堵塞队列//使Cook 和 Foodie使用的同一个队列ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<>(1);//创建线程的对象Cook c = new Cook(abq);Foodie f = new Foodie(abq);//设置线程的名字c.setName("厨师");f.setName("吃货");//开启线程c.start();f.start();}
}

Java多线程里面的六种状态

在Java多线程中,线程共有六种状态,它们分别是:

  1. NEW(新建):这是线程的初始状态。线程对象已经被创建,但是还没有调用start()方法。
  2. RUNNABLE(可运行):这个状态实际上包括了就绪(ready)和运行中(running)两种子状态。当线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法,该线程就进入可运行线程池中,等待被线程调度选中,获取CPU的使用权。此时,线程处于就绪状态。当线程获得CPU时间片后,它就变为运行中状态。
  3. BLOCKED(阻塞):当线程尝试获取某个对象的内置锁,而该锁已经被其他线程持有时,该线程就会进入阻塞状态。此时,线程会暂停执行,直到它获得锁或者等待条件变为真。
  4. WAITING(等待):当线程执行了wait()join()park()等方法时,线程就会进入等待状态。进入该状态的线程需要等待其他线程做出一些特定动作(如通知或中断)才能继续执行。
  5. TIMED_WAITING(定时等待):这个状态与WAITING状态类似,但是线程可以在指定的时间后自行返回,而不需要等待其他线程的动作。这通常是因为线程调用了带有时间参数的sleep()wait()join()等方法。
  6. TERMINATED(终止):当线程执行完毕,或者因为异常而退出时,线程就进入终止状态。这个状态是线程生命周期的最后一个状态。

以上就是Java多线程中的六种状态。

线程池

线程池是Java并发编程中的一种重要技术,它通过预先创建一定数量的线程,并将这些线程放入一个池中,等待任务到来。当有任务到来时,线程池会从池中取出可用的线程来执行任务。这种方式可以有效降低线程创建和销毁的开销,提高系统的性能和稳定性。

使用线程池的一般步骤如下

  1. 创建线程池:Java提供了几种创建线程池的方式,最常用的是使用ThreadPoolExecutor类或者Executors工厂类。例如,可以使用Executors.newFixedThreadPool(int nThreads)来创建一个固定大小的线程池,其中nThreads表示线程池中的线程数。
  2. 提交任务:提交任务到线程池通常有两种方式。一是使用execute()方法提交不需要返回结果的任务;二是使用submit()方法提交需要返回结果的任务。任务需要实现Runnable接口或Callable接口,并重写run()call()方法。
  3. 关闭线程池:在使用完线程池后,需要及时关闭以释放资源。关闭线程池可以使用shutdown()方法。

使用线程池时需要注意以下事项

  1. 合理设置线程池参数:线程池的参数包括核心线程数、最大线程数、任务队列容量、线程空闲时间等。需要根据实际业务场景和需求来合理设置这些参数,以避免资源浪费或性能瓶颈。
  2. 避免任务堆积:当线程池中的线程都在忙碌时,新提交的任务会被放入任务队列中等待执行。如果任务队列容量设置过小,可能会导致任务堆积和响应延迟。因此,需要根据实际情况合理设置任务队列容量。
  3. 处理异常和错误:线程池中的任务执行过程中可能会出现异常和错误。需要在任务实现中妥善处理这些异常和错误,避免影响整个程序的稳定性和可用性。
  4. 合理控制线程数量:过多的线程会消耗大量的系统资源,并可能导致上下文切换过多,从而降低程序的性能。因此,需要根据实际需求和系统资源情况来合理控制线程数量。
  5. 避免死锁和饥饿:多线程编程中容易出现死锁和饥饿等问题。在使用线程池时,需要注意线程之间的同步和通信机制,避免这些问题的发生。
  6. 注意线程安全:线程池中的任务是并发执行的,因此需要注意线程安全问题。在共享数据访问、资源竞争等方面需要采取相应的措施来确保线程安全。

自定义多线池

在Java中,你可以通过实现java.util.concurrent.ExecutorService接口的某个类(通常是ThreadPoolExecutor)来自定义线程池。ThreadPoolExecutor类提供了丰富的配置选项,允许你控制线程池的行为。

以下是一个自定义线程池的示例,使用ThreadPoolExecutor类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class CustomThreadPool {// 创建一个自定义的线程池public static ExecutorService createThreadPool() {// 核心线程数int corePoolSize = 5;// 最大线程数int maxPoolSize = 10;// 线程池维护线程所允许的空闲时间long keepAliveTime = 60L;// 线程池所使用的缓冲队列java.util.concurrent.BlockingQueue<Runnable> workQueue = new java.util.concurrent.LinkedBlockingQueue<Runnable>();// 线程工厂,用于创建新线程java.util.concurrent.ThreadFactory threadFactory = new java.util.concurrent.Executors.DefaultThreadFactory();// 拒绝策略,当任务太多来不及处理,如何拒绝任务java.util.concurrent.RejectedExecutionHandler handler = new java.util.concurrent.ThreadPoolExecutor.AbortPolicy();// 使用ThreadPoolExecutor构造函数创建线程池ExecutorService executorService = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,TimeUnit.SECONDS,workQueue,threadFactory,handler);return executorService;}public static void main(String[] args) {// 获取自定义的线程池ExecutorService executorService = createThreadPool();// 提交任务到线程池for (int i = 0; i < 15; i++) {final int taskId = i;executorService.execute(() -> {System.out.println("Running task with id: " + taskId);// 模拟任务执行时间try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});}// 关闭线程池(先关闭新任务的提交,然后等待已有任务执行完毕)executorService.shutdown();try {// 如果线程池中的任务在指定时间内没有执行完毕,则抛出异常if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {executorService.shutdownNow(); // 强制关闭线程池}} catch (InterruptedException e) {executorService.shutdownNow(); // 强制关闭线程池}}
}

在这个示例中,我们创建了一个自定义的线程池,并设置了核心线程数、最大线程数、线程空闲时间、工作队列、线程工厂和拒绝策略。然后,我们在main方法中提交了一些任务到线程池,并最后关闭了线程池。

注意:shutdown()方法用于平滑地关闭线程池,它会停止接受新任务,但会等待已提交的任务执行完毕。shutdownNow()方法则会尝试立即停止所有正在执行的任务,并返回等待执行的任务列表。如果你希望在关闭线程池时等待一段时间让任务完成,但不想无限期地等待,可以使用awaitTermination()方法。

例子代码

package com.mohuanan.test08;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class Test {public static void main(String[] args) {//自定义线程池对象ThreadPoolExecutor pool = new ThreadPoolExecutor(3,//核心线程的个数6,//最大线程的个数 必须大于核心线程的个数60,//空闲线程的最大空闲时间TimeUnit.MICROSECONDS,//最大空闲时间的单位 使用TimeUnitnew ArrayBlockingQueue<>(30),//堵塞队列 最大值为3new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL精通之路】安全(2)-密码安全

密码出现在MySQL中的多个上下文中。 以下部分提供了一些指导原则&#xff0c;使最终用户和管理员能够确保这些密码的安全并避免暴露这些密码。 此外&#xff0c;validate_password插件可用于强制执行可接受密码的策略。 请参阅“密码验证组件”。 1.密码安全的最终用户指南 …

打造高质感的电子画册,这篇文章告诉你

​在数字化时代&#xff0c;电子画册作为一种全新的视觉传达方式&#xff0c;正逐渐成为各行各业展示形象、传播信息的重要工具。相较于传统的纸质画册&#xff0c;电子画册具有更高的质感、更好的互动性以及更低的制作成本&#xff0c;使得它愈发受到众多企业的青睐。那样怎么…

整理好了!2024年最常见 20 道 Rocket MQ面试题(一)

一、RocketMQ是什么&#xff1f; RocketMQ是一个开源的分布式消息中间件&#xff0c;它最初由阿里巴巴集团开发&#xff0c;并在2012年开源。后来&#xff0c;RocketMQ被捐赠给了Apache软件基金会&#xff0c;并在2017年成为了Apache的顶级项目。以下是RocketMQ的几个关键特点…

linux学习(六)

1.网络管理 (1)查看 ifconfig: root用户可以查看网卡状态, 普通用户: /sbin/ifconfig(需要加上命令的完整路径) (2)修改网络配置 通过命令修改网络配置 设置网卡的ip地址;禁用网卡和启用网卡了。 添加网关: (3)网络故障查询 ①ping 检测当前主机和目标主机是…

单向链表的简单综合应用

通过链表实现赋值&#xff0c;插入&#xff0c;删除&#xff0c;输出的功能&#xff0c;没有多余拉扯&#xff0c;不提供注释&#xff0c;希望大家体会链表之美&#xff1a; 头部 #include<iostream> #include<stdlib.h> using namespace std;typedef struct nod…

杨若歆发布最新单曲《迷雾之谜》从啦啦女神到音乐新星的华丽转身

5月28日&#xff0c;台北——杨若歆&#xff0c;这位被粉丝封为"啦啦女神"的多才多艺艺人&#xff0c;近日推出了她的最新单曲《迷雾之谜》&#xff0c;这首歌曲以其空灵的旋律和杨若歆独特的高音&#xff0c;迅速在歌迷中引起了热烈的反响。 杨若歆&#xff0c;身高…

vxetable 如何修改行点击高亮背景色

在使用vxetable中的表格组件时&#xff0c;有时会遇到修改点击高亮行背景色的情况。要修改高亮行背景色只需要以下两步即可 根据current-change 事件获取并记录当前点击高亮行的点击索引 根据row-style 属性绑定的方法&#xff0c;根据回调参数{rowIndex} ,判断如果当前索引和…

nginx 安全配置

1、前言 前后端分离后&#xff0c;nginx 作为跨域转发工具在日常应用中越来越广泛&#xff0c;它的安全性不能不能忽略。 2、nginx 安装相关说明 2.1 直接下载安装包 在nginx官网下载编译好的安装包&#xff0c;链接地址为nginx: download。如果是linux系统&#xff0c;直接使…

「AIGC算法」R-tree算法

R-tree算法是一种非常实用的空间数据索引技术,它可以帮助我们在复杂的空间数据中快速找到我们想要的信息。下面我将用一些生活中的例子来帮助大家更好地理解R-tree算法。 1. 定义与原理 想象一下,你有一个巨大的图书馆,里面有成千上万本书,每本书都有它在书架上的特定位置…

【Python设计模式01】面向对象基础

1.类与实例 在面向对象编程中&#xff0c;类和实例是两个基本的概念。 类&#xff08;Class&#xff09; 类是对象的蓝图或模板&#xff0c;它定义了一组属性和方法&#xff0c;这些属性和方法将由该类的所有实例共享。类用于封装数据和行为&#xff0c;使代码更加模块化和易…

720VR三维立体小程序源码系统 手机电脑端自适应 前后端分离 带完整的安装代码包以及搭建教程

系统概述 720VR 三维立体小程序源码系统是基于先进的技术和理念打造而成的综合性平台。它融合了虚拟现实技术、移动互联网技术以及计算机编程技术&#xff0c;旨在为用户提供沉浸式的 720 度全景体验。 该系统的设计充分考虑了用户的需求&#xff0c;无论是在手机端还是电脑端…

芯生态 | 鸿道Intewell工业操作系统适配Intel Core i7-8700T

操作系统与芯片在计算机系统中是不可或缺的存在&#xff0c;它们共同协作以确保计算机硬件和软件资源的有效管理和利用、确保系统正常运行和性能优化。 操作系统的设计和实现需要考虑芯片的特性和性能&#xff0c;完美的适配才能充分发挥硬件资源的潜力。下面&#xff0c;小编…

vue-cli2项目中使用scss

前言&#xff1a; 首先要搞清楚Sass和Scss的区别&#xff1a; 实际上Sass和Scss是同一种东西&#xff0c;Scss是 Sass3 引入新的语法&#xff0c;它们都是css预处理器。通常称为Sass&#xff0c;但存在两种不同的语法风格&#xff1a; 文件扩展名&#xff1a;Sass 默认…

探索Python的包与模块:构建项目的基石

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、模块与包的基础认知 1. 模块的定义与创建 2. 包的组织与管理 二、模块与包的进阶使用…

懒人创业秘诀揭秘:加入萤瓴优选项目,普通人也能打开财富大门

创业对于很多人来说&#xff0c;是一个艰难而复杂的过程。然而&#xff0c;时代的发展带来了新的机遇&#xff0c;懒人创业成为了一种趋势。加入萤瓴优选项目&#xff0c;普通人也能轻松打开财富大门。本文将揭秘懒人创业的秘诀&#xff0c;并分析萤瓴优选项目如何帮助普通人实…

极致产品力|从toB到toC,年销4.2亿份的冻干品牌是如何炼成的?

天野食品是日本冻干食品长红40年的品牌&#xff0c;从制造焦糖的小工厂&#xff0c;转变为日本冻干速食的行业第一&#xff0c;它是如何做到的呢? 深耕TOB业务&#xff0c;如何在ToC业务创造增长 天野公司以冻干食品闻名但并非以此起家。自1940年成立以来&#xff0c;便以染料…

tomcat不定时宕机,Failed to write core dump

在linux上的tomcat部署的web应用&#xff0c;不定时会自动挂掉&#xff0c;排查tomcat安装路径/logs/catalina.out 发现提示Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java a…

前端本地项目启动供后端或者测试调试

目录 1、项目本地启动的地址 2、打开终端输入 ifconfig 查找ip 3、将localhost替换成ip即可供他人测试 1、项目本地启动的地址 http://localhost:8100/?module220&webRoutevpc-gray&backRoutevpc-gray........................... 2、打开终端输入 ifconfig 查找i…

android Seek当点击的时候有一个圆圈

最近项目中Seekbar的时候遇到一个问题&#xff1a;点击进度条或者拖动进度条的时候&#xff0c;seekbar出现一个圆形的半透阴影/白色圆圈&#xff1a; <xxxxxxxxxSeekBarandroid:layout_width"wrap_content"android:layout_height"40dp"android:backgro…

DreamPose: Fashion Image-to-Video Synthesis via Stable Diffusion

UW&UCB&Google&NVIDIA ICCV23https://github.com/johannakarras/DreamPose?tabreadme-ov-file 问题引入 输入参考图片 x 0 x_0 x0​和pose序列 { p 1 , ⋯ , p N } \{p_1,\cdots,p_N\} {p1​,⋯,pN​}&#xff0c;输出对应视频 { x 1 ′ , ⋯ , x N ′ } \{x_1,…