java面试题之多线程

news2025/3/19 19:29:18

java面试题之多线程

        • 什么是线程?
        • 什么是线程安全和线程不安全?
        • 什么是⾃旋锁?
        • 什么是CAS?
        • 什么是乐观锁和悲观锁?
        • 什么是AQS?
        • 什么是原⼦操作?在Java Concurrency API中有哪些原⼦类(atomic classes)?
        • 什么是Executors框架?
        • 什么是阻塞队列?如何使⽤阻塞队列来实现⽣产者-消费者模型?
        • 什么是Callable和Future?
        • 什么是FutureTask?
        • 现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行?
        • 在 Java 中 Lock 接口比 synchronized 块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它?
        • 在 java 中 wait 和 sleep 方法的不同?
        • 用 Java 实现阻塞队列。
        • 用 Java 写代码来解决生产者——消费者问题。
        • 用 Java 编程一个会导致死锁的程序,你将怎么解决?
        • 什么是原子操作,Java 中的原子操作是什么?
        • Java 中的 volatile 关键是什么作用?怎样使用它?在 Java 中它跟 synchronized 方法有什么不同?
        • 什么是竞争条件?你怎样发现和解决竞争?
        • 你将如何使用 threaddump?你将如何分析 Thread dump?
        • 为什么我们调用 start()方法时会执行 run()方法,为什么我们不能直接调用 run()方法?
        • Java 中你怎样唤醒一个阻塞的线程?
        • 在 Java 中 CycliBarriar 和 CountdownLatch 有什么区别?
        • 什么是不可变对象,它对写并发应用有什么帮助?
        • 你在多线程环境中遇到的常见的问题是什么?你是怎么解决它的?

什么是线程?

线程是操作系统能够进⾏运算调度的最⼩单位,它被包含在进程之中,是进程中的实际运作单位,可以使⽤多线程对运算进⾏提速。
⽐如,如果⼀个线程完成⼀个任务要100毫秒,那么⽤⼗个线程完成改任务只需10毫秒

什么是线程安全和线程不安全?

线程安全: 就是多线程访问时,采⽤了加锁机制,当⼀个线程访问该类的某个数据时,进⾏保护,其他线程不能进⾏访问,直到该线程读取完,其他线程才可使⽤。不会出现数据不⼀致或者数据污染。
Vector 是⽤同步⽅法来实现线程安全的, ⽽和它相似的ArrayList不是线程安全的。
线程不安全:就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据.
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,⽽⽆写操作,⼀般来说,这个全局变量是线程安全的;若有多个线程同时执⾏写操作,⼀般都需要考虑线程同步,否则的话就可能影响线程安全。

什么是⾃旋锁?

⾃旋锁是SMP架构中的⼀种low-level的同步机制。
1、当线程A想要获取⼀把⾃旋锁⽽该锁⼜被其它线程锁持有时,线程A会在⼀个循环中⾃旋以检测锁是不是已经可⽤了。
2、⾃选锁需要注意:
由于⾃旋时不释放CPU,因⽽持有⾃旋锁的线程应该尽快释放⾃旋锁,否则等待该⾃旋锁的线程会⼀直在那⾥⾃旋,这就会浪费CPU时间。持有⾃旋锁的线程在sleep之前应该释放⾃旋锁以便其它线程可以获得⾃旋锁。
3、⽬前的JVM实现⾃旋会消耗CPU,如果⻓时间不调⽤doNotify⽅法,doWait⽅法会⼀直⾃旋,CPU会消耗太⼤
4、⾃旋锁⽐较适⽤于锁使⽤者保持锁时间⽐较短的情况,这种情况⾃旋锁的效率⽐较⾼。
5、⾃旋锁是⼀种对多处理器相当有效的机制,⽽在单处理器⾮抢占式的系统中基本上没有作⽤。

什么是CAS?

1、CAS(compare and swap)的缩写,中⽂翻译成⽐较并交换。
2、CAS 不通过JVM,直接利⽤java本地⽅ JNI(Java Native Interface为JAVA本地调⽤),直接调⽤CPU 的cmpxchg(是汇编指令)指令。
3、利⽤CPU的CAS指令,同时借助JNI来完成Java的⾮阻塞算法,实现原⼦操作。其它原⼦操作都是利⽤类似的特性完成的。
4、整个java.util.concurrent都是建⽴在CAS之上的,因此对于synchronized阻塞算法,J.U.C在性能上有了很⼤的提升。
5、CAS是项乐观锁技术,当多个线程尝试使⽤CAS同时更新同⼀个变量时,只有其中⼀个线程能更新变量的值,⽽其它线程都失败,失败的线程并不会被挂起,⽽是被告知这次竞争中失败,并可以再次尝试。

1、使⽤CAS在线程冲突严重时,会⼤幅降低程序性能;CAS只适合于线程冲突较少的情况使⽤。
2、synchronized在jdk1.6之后,已经改进优化。synchronized的底层实现主要依靠Lock-Free的队列,基本思路是⾃旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了⾼吞吐量。在线程冲突较少的情况下,可以获得和CAS类似的性能;⽽线程冲突严重的情况下,性能远⾼于CAS。

什么是乐观锁和悲观锁?

乐观锁和悲观锁是并发控制的两种方式,用于解决多个线程或事务同时访问数据时的数据一致性问题。

  • 悲观锁

悲观锁认为数据在并发环境下很可能会发生冲突,所以每次访问数据前,都会先加锁,保证其他线程或事务无法修改数据。
🔹 实现方式
数据库层面:
使用 SELECT … FOR UPDATE 语句,对数据行加锁,其他事务必须等锁释放后才能修改数据。

START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;  -- 加锁
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

应用层面:
使用 synchronized(Java)、ReentrantLock 等方式对资源加锁。
🔹 适用场景
高并发写入场景,数据冲突概率大。
银行转账等对数据一致性要求极高的业务。

  • 乐观锁

乐观锁认为数据冲突的概率比较低,所以不会主动加锁,而是在更新数据时检查数据是否被其他事务修改,如果发生冲突,则让事务失败并重试。
🔹 实现方式
版本号机制:给每行数据增加 version 字段,更新时检查 version 是否一致。

UPDATE accounts 
SET balance = balance - 100, version = version + 1
WHERE id = 1 AND version = 3;

jav代码层次

// AtomicInteger 通过 CAS(Compare and Swap)实现乐观锁
AtomicInteger balance = new AtomicInteger(100);
balance.compareAndSet(100, 90);  // 只有 balance 还是 100 时才能更新,否则失败

时间戳机制:检查 last_update_time 是否发生变化。
🔹 适用场景
读多写少的业务,如用户资料修改、商品库存更新。
提高性能,避免锁带来的性能损耗。

什么是AQS?

1、AbstractQueuedSynchronizer简称AQS,是⼀个⽤于构建锁和同步容器的框架。事实上concurrent包内许多类都是基
于AQS构建,例如ReentrantLock,Semaphore,CountDownLatch,ReentrantReadWriteLock,FutureTask等。AQS解
决了在实现同步容器时设计的⼤量细节问题。
2、AQS使⽤⼀个FIFO的队列表示排队等待锁的线程,队列头节点称作“哨兵节点”或者“哑节点”,它不与任何线程关联。
其他的节点与等待线程关联,每个节点维护⼀个等待状态waitStatus。

什么是原⼦操作?在Java Concurrency API中有哪些原⼦类(atomic classes)?

1、原⼦操作是指⼀个不受其他操作影响的操作任务单元。原⼦操作是在多线程环境下避免数据不⼀致必须的⼿段。
2、int++并不是⼀个原⼦操作,所以当⼀个线程读取它的值并加1时,另外⼀个线程有可能会读到之前的值,这就会引发
错误。
3、为了解决这个问题,必须保证增加操作是原⼦的,在JDK1.5之前我们可以使⽤同步技术来做到这⼀点。
到JDK1.5,java.util.concurrent.atomic包提供了int和long类型的装类,它们可以⾃动的保证对于他们的操作是原⼦的并
且不需要使⽤同步。

什么是Executors框架?

Java通过Executors提供四种线程池,分别为:
1、newCachedThreadPool创建⼀个可缓存线程池,如果线程池⻓度超过处理需要,可灵活回收空闲线程,若⽆可回收,则新建线程。
2、newFixedThreadPool 创建⼀个定⻓线程池,可控制线程最⼤并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool 创建⼀个定⻓线程池,⽀持定时及周期性任务执⾏。
4、newSingleThreadExecutor 创建⼀个单线程化的线程池,它只会⽤唯⼀的⼯作线程来执⾏任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执⾏。

什么是阻塞队列?如何使⽤阻塞队列来实现⽣产者-消费者模型?

1、JDK7提供了7个阻塞队列。(也属于并发容器)
i. ArrayBlockingQueue :⼀个由数组结构组成的有界阻塞队列。
ii. LinkedBlockingQueue :⼀个由链表结构组成的有界阻塞队列。
iii. PriorityBlockingQueue :⼀个⽀持优先级排序的⽆界阻塞队列。
iv. DelayQueue:⼀个使⽤优先级队列实现的⽆界阻塞队列。
v. SynchronousQueue:⼀个不存储元素的阻塞队列。
vi. LinkedTransferQueue:⼀个由链表结构组成的⽆界阻塞队列。
vii. LinkedBlockingDeque:⼀个由链表结构组成的双向阻塞队列。
2、概念:阻塞队列是⼀个在队列基础上⼜⽀持了两个附加操作的队列。
3、2个附加操作:
⽀持阻塞的插⼊⽅法:队列满时,队列会阻塞插⼊元素的线程,直到队列不满。⽀持阻塞的移除⽅法:队列空时,获取元素的线程会等待队列变为⾮空。

什么是Callable和Future?

1、Callable 和 Future 是⽐较有趣的⼀对组合。当我们需要获取线程的执⾏结果时,就需要⽤到它们。Callable⽤于产⽣结果,Future⽤于获取结果。
2、Callable接⼝使⽤泛型去定义它的返回类型。Executors类提供了⼀些有⽤的⽅法去在线程池中执⾏Callable内的任务。由于Callable任务是并⾏的,必须等待它返回的结果。java.util.concurrent.Future对象解决了这个问题。
3、在线程池提交Callable任务后返回了⼀个Future对象,使⽤它可以知道Callable任务的状态和得到Callable返回的执⾏结果。Future提供了get()⽅法,等待Callable结束并获取它的执⾏结果。

什么是FutureTask?

1、FutureTask可⽤于异步获取执⾏结果或取消执⾏任务的场景。通过传⼊Runnable或者Callable的任务给FutureTask,直接调⽤其run⽅法或者放⼊线程池执⾏,之后可以在外部通过FutureTask的get⽅法异步获取执⾏结果,因此,FutureTask⾮常适合⽤于耗时的计算,主线程可以在完成⾃⼰的任务后,再去获取结果。另外,FutureTask还可以确保即使调⽤了多次run⽅法,它都只会执⾏⼀次Runnable或者Callable任务,或者通过cancel取消FutureTask的执⾏等。
2、futuretask可⽤于执⾏多任务、以及避免⾼并发情况下多次创建数据机锁的出现。

现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行?
  • 使用 join()

join() 方法会阻塞当前线程,直到目标线程执行完毕。因此,我们可以让 T2 在 T1.join() 后执行,T3 在 T2.join() 后执行:

import threading

def task1():
    print("T1 is running")

def task2():
    print("T2 is running")

def task3():
    print("T3 is running")

# 创建线程
t1 = threading.Thread(target=task1)
t2 = threading.Thread(target=task2)
t3 = threading.Thread(target=task3)

# 启动线程
t1.start()
t1.join()  # 等待 T1 执行完毕

t2.start()
t2.join()  # 等待 T2 执行完毕

t3.start()
t3.join()  # 等待 T3 执行完毕

优点:
代码简单,逻辑清晰。
缺点:
每个线程必须等前一个线程执行完毕后才能启动,失去了多线程的并发优势。

  • 使用 CountDownLatch

CountDownLatch 允许多个线程等待某个条件满足后再执行。

import java.util.concurrent.CountDownLatch;

public class ThreadOrder {
    public static void main(String[] args) {
        CountDownLatch latch1 = new CountDownLatch(1);
        CountDownLatch latch2 = new CountDownLatch(1);

        Thread t1 = new Thread(() -> {
            System.out.println("T1 is running");
            latch1.countDown(); // 释放 T2
        });

        Thread t2 = new Thread(() -> {
            try {
                latch1.await(); // 等待 T1 执行完
                System.out.println("T2 is running");
                latch2.countDown(); // 释放 T3
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                latch2.await(); // 等待 T2 执行完
                System.out.println("T3 is running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

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

缺点:
CountDownLatch 只能使用一次,不能重置。
优点:
允许一定的并发,不会完全阻塞其他线程。

  • 使用 CyclicBarrier

CyclicBarrier 允许线程等待其他线程到达屏障后继续执行。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class ThreadOrder {
    public static void main(String[] args) {
        CyclicBarrier barrier1 = new CyclicBarrier(2); // 需要两个线程到达
        CyclicBarrier barrier2 = new CyclicBarrier(2);

        Thread t1 = new Thread(() -> {
            System.out.println("T1 is running");
            try {
                barrier1.await(); // 释放 T2
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                barrier1.await(); // 等待 T1 执行完
                System.out.println("T2 is running");
                barrier2.await(); // 释放 T3
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                barrier2.await(); // 等待 T2 执行完
                System.out.println("T3 is running");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        });

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

优点:
CyclicBarrier 可重复使用,适用于循环任务。
缺点:
逻辑稍微复杂,适用于多个线程的同步控制。

  • 使用 Semaphore

Semaphore 允许我们控制线程的执行顺序,只有获得许可的线程才能执行。

import java.util.concurrent.Semaphore;

public class ThreadOrder {
    public static void main(String[] args) {
        Semaphore sem1 = new Semaphore(0);
        Semaphore sem2 = new Semaphore(0);

        Thread t1 = new Thread(() -> {
            System.out.println("T1 is running");
            sem1.release(); // 允许 T2 运行
        });

        Thread t2 = new Thread(() -> {
            try {
                sem1.acquire(); // 等待 T1 运行完
                System.out.println("T2 is running");
                sem2.release(); // 允许 T3 运行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                sem2.acquire(); // 等待 T2 运行完
                System.out.println("T3 is running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

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

优点:
Semaphore 适用于资源控制和同步操作。
缺点:
需要手动管理信号量,代码稍微复杂。

  • 使用 FutureTask

FutureTask 结合 ExecutorService 可以确保线程按顺序执行。

import java.util.concurrent.*;

public class ThreadOrder {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        Future<?> future1 = executor.submit(() -> System.out.println("T1 is running"));
        future1.get(); // 等待 T1 结束

        Future<?> future2 = executor.submit(() -> System.out.println("T2 is running"));
        future2.get(); // 等待 T2 结束

        Future<?> future3 = executor.submit(() -> System.out.println("T3 is running"));
        future3.get(); // 等待 T3 结束

        executor.shutdown();
    }
}

优点:
使用线程池管理线程,避免创建太多线程开销。
缺点:
需要显式调用 get(),否则不会阻塞等待。

在 Java 中 Lock 接口比 synchronized 块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它?

lock 接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像
ConcurrentHashMap 这样的高性能数据结构和有条件的阻塞。Java 线程面试的问题越来越会
根据面试者的回答来提问。我强烈建议在你去参加多线程的面试之前认真读一下 Locks,因
为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。

在 java 中 wait 和 sleep 方法的不同?

最大的不同是在等待时 wait 会释放锁,而 sleep 一直持有锁。Wait 通常被用于线程间交互,sleep 通常被用于暂停执行。

用 Java 实现阻塞队列。

这是一个相对艰难的多线程面试问题,它能达到很多的目的。第一,它可以检测侯选者是否能实际的用 Java 线程写程序;第二,可以检测侯选者对并发场景的理解,并且你可以根据这个问很多问题。如果他用wait()和 notify()方法来实现阻塞队列,你可以要求他用最新的Java 5 中的并发类来再写一次。

用 Java 写代码来解决生产者——消费者问题。

与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在 Java 中怎
么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的
方法。有些时候他们甚至会问怎么实现哲学家进餐问题。

用 Java 编程一个会导致死锁的程序,你将怎么解决?

这是我最喜欢的 Java 线程面试问题,因为即使死锁问题在写多线程并发程序时非常普遍,
但是很多侯选者并不能写 deadlock free code(无死锁代码?),他们很挣扎。只要告诉他们,
你有 N 个资源和 N 个线程,并且你需要所有的资源来完成一个操作。为了简单这里的 n 可
以替换为 2,越大的数据会使问题看起来更复杂。通过避免 Java 中的死锁来得到关于死锁的
更多信息。

什么是原子操作,Java 中的原子操作是什么?

非常简单的 java 线程面试问题,接下来的问题是你需要同步一个原子操作。

Java 中的 volatile 关键是什么作用?怎样使用它?在 Java 中它跟 synchronized 方法有什么不同?

自从 Java 5 和 Java 内存模型改变以后,基于 volatile 关键字的线程问题越来越流行。应该准
备好回答关于 volatile 变量怎样在并发环境中确保可见性。

什么是竞争条件?你怎样发现和解决竞争?

这是一道出现在多线程面试的高级阶段的问题。大多数的面试官会问最近你遇到的竞争条件,
以及你是怎么解决的。有些时间他们会写简单的代码,然后让你检测出代码的竞争条件。可
以参考我之前发布的关于 Java 竞争条件的文章。在我看来这是最好的 java 线程面试问题之
一,它可以确切的检测候选者解决竞争条件的经验,or writing code which is free of data race
or anyother race condition。关于这方面最好的书是《Concurrency practices in Java》

你将如何使用 threaddump?你将如何分析 Thread dump?

在 UNIX 中你可以使用 kill -3,然后 thread dump 将会打印日志,在 windows 中你可以使用”
CTRL+Break”。非常简单和专业的线程面试问题,但是如果他问你怎样分析它,就会很棘手。

为什么我们调用 start()方法时会执行 run()方法,为什么我们不能直接调用 run()方法?

这是另一个非常经典的 java 多线程面试问题。这也是我刚开始写线程程序时候的困惑。现
在这个问题通常在电话面试或者是在初中级 Java 面试的第一轮被问到。这个问题的回答应
该是这样的,当你调用 start()方法时你将创建新的线程,并且执行在 run()方法里的代码。但
是如果你直接调用 run()方法,它不会创建新的线程也不会执行调用线程的代码。阅读我之
前写的《start 与 run 方法的区别》这篇文章来获得更多信息。

Java 中你怎样唤醒一个阻塞的线程?

这是个关于线程和阻塞的棘手的问题,它有很多解决方法。如果线程遇到了 IO 阻塞,我并
且不认为有一种方法可以中止线程。如果线程因为调用 wait()、sleep()、或者 join()方法而导
致的阻塞,你可以中断线程,并且通过抛出 InterruptedException 来唤醒它。我之前写的《How
to deal with blocking methods in java》有很多关于处理线程阻塞的信息。

在 Java 中 CycliBarriar 和 CountdownLatch 有什么区别?

这个线程问题主要用来检测你是否熟悉 JDK5 中的并发包。这两个的区别是 CyclicBarrier 可以
重复使用已经通过的障碍,而 CountdownLatch 不能重复使用。

什么是不可变对象,它对写并发应用有什么帮助?

另一个多线程经典面试问题,并不直接跟线程有关,但间接帮助很多。这个 java 面试问题
可以变的非常棘手,如果他要求你写一个不可变对象,或者问你为什么 String 是不可变的。

你在多线程环境中遇到的常见的问题是什么?你是怎么解决它的?

多线程和并发程序中常遇到的有 Memory-interface、竞争条件、死锁、活锁和饥饿。问题是没有止境的,如果你弄错了,将很难发现和调试。这是大多数基于面试的,而不是基于实际应用的 Java 线程问题。

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

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

相关文章

FPGA-流水灯

Quartus中使用Verilog实现 根据之前所学内容&#xff0c;打开Quartus 软件&#xff0c;新建FPGA项目文件&#xff0c;建立好空项目过后&#xff0c;选择Verilog HDL File&#xff0c;因为我们要使用Verilog代码实现仿真。 详细操作可参考往期博客&#xff1a; FPGA 实验报告&a…

browser-use WebUI + DeepSeek 基于AI的UI自动化解决方案

browser-use WebUI 一、browser-use是什么Browser-use采用的技术栈为&#xff1a; 二、browser-use webui 主要功能使用场景 三、使用教程1.python 安装2、把项目clone下来3、安装依赖4、配置环境5、启动6、配置1.配置 Agent2.配置要用的大模型3.关于浏览器的一些设置 四、Deep…

什么是YApi?开源接口管理平台部署教程

YApi 到底是个啥&#xff1f; 各位小伙伴们好呀&#xff01;今天要给大家介绍的是一款超级好用的接口管理神器——YApi&#xff01;它是一个高效、易用、功能强大的 API 管理平台&#xff0c;简直就是开发、产品、测试人员的福音啊&#xff01;&#xff01;&#xff01;它能帮…

深入理解事务

在数据库管理中&#xff0c;事务是一个至关重要的概念。无论是金融交易、库存管理还是用户数据更新&#xff0c;事务都确保了数据的完整性和一致性。本文将详细介绍为什么需要事务、什么是事务、事务的四大特征、如何在MySQL中使用事务以及MyBatis对事务的配置。 一、为什么需…

基于SpringBoot + Vue 的药店药品信息管理系统

基于SpringBootVue的药品药店药房信息系统(带文档) 角色: 用户&#xff0c;管理员&#xff0c;员工 功能: 管理员: 首页、个人中心、用户管理、员工管理、药品类别管理、药品信息管理、药品入库管理、药品出库管理、在线咨询管理、留言板管理、系统管理、订单管理。 用户:…

ubuntu下TFTP服务器搭建

tftp 命令的作用和 nfs 命令一样&#xff0c;都是用于通过网络下载东西到 DRAM 中&#xff0c;只是 tftp 命令 使用的 TFTP 协议&#xff0c; Ubuntu 主机作为 TFTP 服务器。因此需要在 Ubuntu 上搭建 TFTP 服务器&#xff0c; 需要安装 tftp-hpa 和 tftpd-hpa&#xff0c;命令…

解决:ModuleNotFoundError: No module named ‘_sqlite3‘

报错&#xff1a; from _sqlite3 import * ModuleNotFoundError: No module named _sqlite3安装sqlite3支持组件: sudo apt-get install libsqlite3-dev进入之前下载的python包下&#xff0c;重新编译和安装Python ./configure --enable-loadable-sqlite-extensions make &a…

技术债务的隐患:何时重构,何时妥协?

在快节奏的软件开发环境中&#xff0c;企业为了抢占市场或满足紧迫需求&#xff0c;往往不得不在短期内采取“捷径”来加速产品交付&#xff0c;这便引入了“技术债务”。短期内看似能迅速交付&#xff0c;但随着时间推移&#xff0c;这些未优化的代码和架构缺陷会逐渐累积&…

c#Winform也可以跨平台了GTK框架GTKSystem.Windows.Forms

一、简介 >> 新版下载&#xff0c;问题求助 QQ群&#xff1a;1011147488 1032313876 236066073&#xff08;满&#xff09; Visual Studio原生开发&#xff0c;无需学习&#xff0c;一次编译&#xff0c;跨平台运行. C#桌面应用程序跨平台&#xff08;windows、linux、…

ABAP PDF预览

画个屏幕 PDF JPG TXT都可以参考预览&#xff0c;把二进制流传递给标准函数就行 *&---------------------------------------------------------------------* *& Report YDEMO2 *&---------------------------------------------------------------------* *&am…

网络爬虫【爬虫库urllib】

我叫不三不四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲爬虫 urllib介绍 Urllib是Python自带的标准库&#xff0c;无须安装&#xff0c;直接引用即可。 Urllib是一个收集几个模块来使用URL的软件包&#xff0c;大致具备以下功能。 ● urlli…

卷积神经网络 - 卷积层

卷积神经网络一般由卷积层、汇聚层和全连接层构成&#xff0c;本文我们来学习卷积层。 卷积层&#xff08;Convolutional Layer&#xff09;是卷积神经网络&#xff08;CNN&#xff09;的核心组件&#xff0c;专门用于处理具有网格结构的数据&#xff08;如图像、音频、时间序…

玩转 Tailwind CSS:深入解析函数与指令

玩转 Tailwind CSS&#xff1a;深入解析函数与指令 如果你正在使用 Tailwind CSS&#xff0c;可能已经习惯了各种 text-center、mt-4 这样的类名&#xff0c;但你知道吗&#xff1f;Tailwind 其实还隐藏着一套 强大的函数与指令系统&#xff0c;可以让你的代码更加优雅、可维护…

Axure设计之下拉多选框制作教程C(中继器)

利用Axure制作下拉多选器组件可以极大地提升原型制作的效率和效果。以下是基于你提供的详细步骤的详细指导&#xff0c;帮助你在Axure中实现一个功能完善、高保真且可复用的下拉多选器组件。 一、案例预览 预览地址&#xff1a;https://pghy0i.axshare.com 实现效果包括&#…

Java基础语法练习42(基本绘图-基本的事件处理机制-小坦克的绘制-键盘控制坦克移动)

目录 一、图形的基本绘制 1.基本介绍&#xff1a; 2.入门代码如下&#xff1a; 3.常用图形的绘制, 示例代码如下&#xff1a; 二、坦克的绘制 三、事件处理机制 四、坦克的移动 一、图形的基本绘制 1.基本介绍&#xff1a; Component 类提供了两个和绘图相关最重要的方…

RabbitMQ 入门

RabbitMQ 入门 1RabbitMQ 介绍 RabbitMQ 是信息传输的中间者。本质上&#xff0c;他从生产者&#xff08;producers&#xff09;接收消息&#xff0c;转发这些消息给消费者&#xff08;consumers&#xff09;.换句话说&#xff0c;他能够按根据你指定的规则进行消息转发、缓冲…

yolo环境 pytorch环境配置 CUDA安装

我的成功案例&#xff1a;首先安装python 3.12.9的conda虚拟环境 &#xff08;如果不安装3.12的会报错误ModuleNotFoundError&#xff1a;没有名为“numpy._core”的模块&#xff09; 然后安装11.8cuda &#xff08;其实我是可以最高安装12.6的cuda但我实测&#xff0c;太高版…

ESP32(4)TCP通信

本章重点讲解 lwIP 的 Socket接口如何配置 TCP客户端&#xff0c;并在此基础上实现收发功能。 TCP Client 连接流程 在实现 TCP 协议之前&#xff0c;用户需要按照以下步骤配置结构体 sockaddr_in 的成员变量&#xff0c;以便建立 TCPClient 连接&#xff1a; ①&#xff1a;…

数学建模:MATLAB循环神经网络

一、简述 1.循环神经网络 循环神经网络&#xff08;RNN&#xff09;是一种用于处理序列数据的神经网络。不同于传统的前馈神经网络&#xff0c;RNN在隐藏层中加入了自反馈连接&#xff0c;使得网络能够对序列中的每个元素执行相同的操作&#xff0c;同时保持一个“记忆”状态…

EagleTrader为何重申重要数据前后2分钟禁止交易?

3月12日&#xff0c;美国公布了2月份的CPI数据。 美国2月未季调CPI年率录得2.8%&#xff0c;为去年11月来新低&#xff0c;低于市场预期的2.9%。 美国2月季调后CPI月率录得0.2%&#xff0c;为去年10月来新低&#xff0c;预期值为0.3%&#xff0c;前值为0.5%。 数据公布后&#…