Java 面试复习_3

2026年Java后端面试3天高效复习指南:从八股文到实战思维 Java后端开发作为企业级应用的核心技术栈,其知识体系涵盖语言基础、框架原理、分布式架构等多个层面。理解技术选型背后的设计思想,比如在MySQL与Redis之间根据数据一致性需求做出权衡,或基于业务场景设计微服务拆分方案,是工程师从“会用”到“精通”的关键跃迁。这种技术判断能力在面试中尤为重要,尤其是在云原生和分布式系统成为主流的技术趋势下。本文以2026年Java后端面试为例,结合高频八股文和实战场景,系统讲解如何通过3天时间快速构建技术脉络,重点覆盖容器化部署、分布式事务等热点问题,帮助求职者将知识点转 阅读详情


2019-5-19
作者:水不要鱼

(注:能力有限,如有说错,请指正!)

  • 创建线程的方式

  1. 继承 Thread 类,并重写 run() 方法,这种方式有局限性,由于 Java 中是单继承的,
    所以继承了 Thread 类就意味着不能再继承别的类了
  2. 实现 Runnable 接口,实现 run() 方法,这种方式不存在单继承的局限性,但是它没有返回值,
    所以如果执行的任务需要返回数据,就只能使用数据共享的方式来获得执行结果了
  3. 实现 Callable 接口,实现 call() 方法,这种方式需要先将 Callable 对象包装成 FutureTask 对象,
    因为 Thread 的构造器就是支持 Runnable 对象,但好处就是,它可以拿到返回值
class Test {
    // 继承 Thread 类
    static class Thread1 extends Thread {
        @Override
        public void run() {
            // 获取当前线程:this
            System.out.println("我是 " + this.getName());
        }
    }
    
    // 实现 Runnable 接口
    static class Thread2 implements Runnable {
        @Override
        public void run() {
            // 获取当前线程:Thread.currentThread()
            System.out.println("我是 " + Thread.currentThread().getName());
        }
    }
    
    // 实现 Callable 接口
    static class Thread3 implements Callable<Void> {
        @Override
        public Void call() throws Exception {
            // 获取当前线程:Thread.currentThread()
            System.out.println("我是 " + Thread.currentThread().getName());
            return null;
        }
    }
    
    public static void main(String[] args) throws Exception {
    
        new Thread1().start();
        new Thread(new Thread2()).start();
        
        // 注意这里需要将 Callable 包装成 FutureTask
        // 实际上,FutureTask 实现了 Runnable 接口,所以才能传给 Thread
        FutureTask task = new FutureTask<>(new Thread3());
        new Thread(task).start();
        
        // 获得返回值,这是阻塞方法,
        // 建议使用带等待时间的 get(long timeout, TimeUnit unit)
        task.get();
    }
}

扩展:线程池

我们知道线程的创建和销毁是需要消耗性能的,而且操作系统对于线程的数量一般都会有限制,
所以我们需要一种保障,它需要满足两点:1. 线程复用,减少创建和销毁的性能消耗;2. 限制线程数量,以免线程数量太多导致过多的线程上下文切换,甚至把操作系统搞崩。

这种保障就是线程池。从字面意思很好理解,就是一个装满线程的池子,需要的时候就从里面拿一个线程,
用完了就放回去,和共享有点像。JDK 中提供了一个线程池类:ThreadPoolExecutor,构造参数如下:

class ThreadPoolExecutor {
    public ThreadPoolExecutor(
            int corePoolSize, // 核心线程数
            int maximumPoolSize, // 最大线程数
            long keepAliveTime, // 线程空闲存活时间
            TimeUnit unit, // 存活时间单位
            BlockingQueue<Runnable> workQueue, // 任务缓冲队列
            ThreadFactory threadFactory, // 线程工厂
            RejectedExecutionHandler handler // 线程池不能再处理任务的时候,执行的拒绝策略
            ) {
        // 省略源码。。。
    }
}

线程池内部是这样工作的:

  1. 当线程池线程数量还没达到核心线程数的时候,每来一个任务,如果没有空闲线程可以执行的话,就创建一个新线程去执行任务
  2. 当线程池线程数量已经达到核心线程数的时候,再来任务,如果没有空闲线程可以执行的话,就将任务放入任务缓冲队列
  3. 线程池中的线程会不断从任务缓冲队列中取任务执行,这个队列是阻塞的,也就是拿不到任务的话,就会等待新任务的到来
  4. 当任务缓冲队列也被填满了,就会再次创建线程,这部分线程将被标记为非核心数量线程,因为它们是介于核心线程数和最大线程数之间的线程
  5. 最终,线程数量达到了最大线程数,整个线程池便进入忙碌状态,这时候提交任务,就会执行拒绝策略

从上面我们可以看到,如果最大线程数是 Integer.MAX_VALUE,拒绝策略也就不会被执行,
因为不存在线程池满的情况。如果队列是无界的,就有可能撑爆服务器内存。

我们再来仔细看看上面的一些参数:

  1. keepAliveTime,线程空闲存活时间

上面说过,如果线程池数量已经达到核心线程数了,再创建出来的线程就会被标记为非核心线程,
当这些被标记为非核心线程的线程空闲的时间达到了 keepAliveTime 之后,就会被回收销毁。

那核心线程有没有可能被销毁呢?有的,在这个类中有一个方法:void allowCoreThreadTimeOut(boolean value),
可以设置核心线程也会被超时回收,也就是说核心线程和非核心线程的待遇一样了,这点从源码中可以看到:

class ThreadPoolExecutor {
    /**
    * If false (default), core threads stay alive even when idle.
    * If true, core threads use keepAliveTime to time out waiting
    * for work.
    */
    private volatile boolean allowCoreThreadTimeOut;
}
  1. workQueue,任务缓冲队列

这个参数的类型是 BlockingQueue ,这是一个接口,而且带了泛型,也就是说最终放进队列的一定是 Runnable 对象,
另外,这是个 BlockingQueue 也就是阻塞队列。阻塞的意思就是当拿不到东西的时候就会等待,当放不进东西的时候也会等待。
这个接口有一些方法很有意思:

  • boolean add(E e):这个方法很霸道,一旦队列满了,添加元素失败,就会爆出 IllegalStateException 异常
  • boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException:
    如果添加失败,会等待特定的时间,时间到了还是添加不成功就会直接返回了,润物细无声,你甚至不知道它还在等你哈哈
  • E poll(long timeout, TimeUnit unit) throws InterruptedException:和 offer 类似,
    一段时间等不到就不等了,我猜它心里肯定是这么想的:老娘又不是没人要,哼,渣男!
  • void put(E e) throws InterruptedException:这个方法也很霸道,因为你仔细看的话会发现,它没有返回值!
    意思就是它只能成功,不能失败,所以返回值就没有意义了。保证成功的秘诀就是,死等,只要没有人中断,就等待。
  • E take() throws InterruptedException:和 put 类似,死等直到能拿到元素为止

在 JDK 中提供了很多的 BlockingQueue 实现类:

  • ArrayBlockingQueue:底层使用数组来实现,并且提供了容量限制,一定要给初始化容量,这个值将根据业务的量来定,
    开的太大会浪费内存,开的太小,很容易满,就会导致新创建线程甚至是执行拒绝策略

  • LinkedBlockingQueue:底层使用链表来实现,它提供了默认容量,大小为 Integer.MAX_VALUE,
    这意味着如果不指定大小,它将会消耗大量的内存,如果超过了机器的内存大小,就会导致内存溢出。所以在使用的时候,
    还是建议手动指定大小

  • SynchronousQueue:这是最诡异的一个队列,它的容量为 0,也就是你不能添加任何的元素进去,执行 offer 方法永远返回 false,执行 poll() 永远返回 null。从源码注释中,我发现了这样一段话:

Synchronous queues are similar to rendezvous channels used in CSP and Ada.

也就是说,这个队列是类似于 CSP 并发模型中的 channel 的,比如 Go 中的 channel。
在 Java 中,我搜索了一遍,发现除了 Executors 这些有用到它之外,还有 com.sun.webkit.network.SocketStreamHandle 这个类有用到,但也仅仅只是用来初始化线程池,没有拿来作 channel 使用。所以这个队列在 Java 中貌似就是空队列的存在

另外,这个队列支持公平和非公平,我们来看源码:

class SynchronousQueue {
    /**
    * Creates a {@code SynchronousQueue} with the specified fairness policy.
    *
    * @param fair if true, waiting threads contend in FIFO order for
    *        access; otherwise the order is unspecified.
    */
    public SynchronousQueue(boolean fair) {
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }
}

很明显,当设置为公平时,就是 TransferQueue 对象,也就是 FIFO 的队列,反之,非公平就是 TransferStack 对象
在源码中我还发现一堆很有趣的东西:

class SynchronousQueue {
    /*
    * To cope with serialization strategy in the 1.5 version of
    * SynchronousQueue, we declare some unused classes and fields
    * that exist solely to enable serializability across versions.
    * These fields are never used, so are initialized only if this
    * object is ever serialized or deserialized.
    */
    
    @SuppressWarnings("serial")
    static class WaitQueue implements java.io.Serializable { }
    static class LifoWaitQueue extends WaitQueue {
        private static final long serialVersionUID = -3633113410248163686L;
    }
    static class FifoWaitQueue extends WaitQueue {
        private static final long serialVersionUID = -3623113410248163686L;
    }
    private ReentrantLock qlock;
    private WaitQueue waitingProducers;
    private WaitQueue waitingConsumers;
}

我跟踪使用的地方,发现只有两个地方有用到:

class SynchronousQueue {
    /**
    * Saves this queue to a stream (that is, serializes it).
    * @param s the stream
    * @throws java.io.IOException if an I/O error occurs
    */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        boolean fair = transferer instanceof TransferQueue;
        if (fair) {
            qlock = new ReentrantLock(true);
            waitingProducers = new FifoWaitQueue();
            waitingConsumers = new FifoWaitQueue();
        }
        else {
            qlock = new ReentrantLock();
            waitingProducers = new LifoWaitQueue();
            waitingConsumers = new LifoWaitQueue();
        }
        s.defaultWriteObject();
    }
    
    /**
    * Reconstitutes this queue from a stream (that is, deserializes it).
    * @param s the stream
    * @throws ClassNotFoundException if the class of a serialized object
    *         could not be found
    * @throws java.io.IOException if an I/O error occurs
    */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        if (waitingProducers instanceof FifoWaitQueue)
            transferer = new TransferQueue<E>();
        else
            transferer = new TransferStack<E>();
    }
}

换而言之,就是序列化的时候要用到,一个空队列居然也要序列化??搞不懂 Doug Lea 的想法,
或许这个队列还有其他很大的作用,只是我们还没有发现

  • PriorityBlockingQueue:优先队列,底层使用数组模拟的堆结构实现,
    和 java.util.PriorityQueue 的功能一样,只是它是阻塞的。可以指定初始化容量,而且内部还保存了一个 PriorityQueue 用于序列化,
    也就是在 writeObject 中将数据写入内部这个的 PriorityQueue,然后序列化这个 PriorityQueue,
    在 readObject 中从 PriorityQueue 中读取数据并初始化 PriorityBlockingQueue

  • DelayQueue:延迟队列,底层使用优先队列来排序时间,也就是说,当你向这个队列添加元素的时候,它会根据这个元素的延迟时间来升序排序,
    这样最先出队的就是延迟最低时间最短的那个元素了。那元素的延迟时间怎么设置?我们可以发现,这个类的定义是有泛型的:

public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
    implements BlockingQueue<E> {}

这个泛型 E extends Delayed 就意味着入队的元素必须实现 java.util.concurrent.Delayed 接口,
进而实现 long getDelay(TimeUnit unit) 方法来设置元素的延迟时间。这个队列使用了 Leader-Follower 模式来减少等待的时间,
感兴趣的可以去搜相关内容

还有一个类和这个类很相似,那就是 java.util.concurrent.ScheduledThreadPoolExecutor.DelayedWorkQueue 队列,
但是这个队列没有直接使用优先队列,而是又重写了堆结构,同样要求元素实现 java.util.concurrent.Delayed 接口

  1. handler,拒绝策略

上面说过,当线程池满了的时候,就会执行拒绝策略。这个参数是 java.util.concurrent.RejectedExecutionHandler 接口,
里面有一个 void rejectedExecution(Runnable r, ThreadPoolExecutor executor) 方法,我们可以自己定义拒绝策略,
用于不同的业务需求。

比如说,你这个线程池的任务不允许有一丝的丢失,而线程池又不可能一直处理任务,
你就可以定义一个拒绝策略:

class NotRejectedExecutionHandler implements RejectedExecutionHandler {
    // 重试次数
    // 保存操作有可能失败,所以需要重试,但是不能一直重试,
    // 必须要有个重试次数限制,否则就会导致资源浪费
    private static final int RETRY_TIMES = 3;
    
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    // Runnable r: 被拒绝的任务对象
    // ThreadPoolExecutor executor: 当前执行任务的这个线程池
    
    // 场景假设:不允许丢失任何一个任务
    // 我们可以将任务对象持久化,比如保存在数据库中,
    // 之后由定时任务来从数据库取出任务执行
    int retryTimes = 0;
    while (!save(r)) {
        retryTimes++;
        if (retryTimes > RETRY_TIMES) {
            // 如果重试了三次都失败了,就需要采取应急措施
            notifyWorker(r);
            break;
        }
    }
    
    private boolean save(Runnable task) {
        // 数据库保存操作...
        return true;
    }
    
    private void notifyWorker(Runnable r) {
        // 日志记录,或者发邮件通知运维人员之类的...
        // 由于这已经是应急操作了,所以日志记录是必须的
        // 而且为了保证应急操作成功,最好执行一些失败率很低的操作
    }
}

上面只是举了一个例子,你还可以将任务保存在缓存系统或者消息队列中,这些都需要根据实际业务来定。
如果你没有指定这个参数,就会使用默认的拒绝策略,也就是直接抛异常:

class ThreadPoolExecutor {
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 threadFactory, defaultHandler);
        // 这里的 defaultHandler 就是下面的 AbortPolicy
    }
    
    /**
    * The default rejected execution handler
    */
    private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
    
    /**
    * A handler for rejected tasks that throws a
    * {@code RejectedExecutionException}.
    */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
        * Creates an {@code AbortPolicy}.
        */
        public AbortPolicy() {}

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                          " rejected from " + e.toString());
        }
    }
}

除了上面的 AbortPolicy 默认拒绝策略之外,还有几个内置的拒绝策略:

  • CallerRunsPolicy:在调用者线程执行这个任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code CallerRunsPolicy}.
     */
    public CallerRunsPolicy() {}
    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            // 直接执行这个 run 方法
            r.run();
        }
    }
}
  • DiscardOldestPolicy:丢掉最老的元素,空出位置执行这个被拒绝的任务
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code DiscardOldestPolicy} for the given executor.
     */
    public DiscardOldestPolicy() {}
    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            // 将队列的第一个元素移除,空出位置来,然后再将任务加进去执行
            e.getQueue().poll();
            e.execute(r);
        }
    }
}
  • DiscardPolicy:这是最简单的策略了,就是直接拒绝,也不会抛出异常,
    就是很安静的抛弃掉任务,无声无息,悄悄地就走了
public static class DiscardPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code DiscardPolicy}.
     */
    public DiscardPolicy() {}
    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // 啥也不干
    }
}
  • JDK 内置线程池

在 JDK 中提供了 Executors 工具类,里面有几个工厂方法,可以快速创建几种线程池:

  1. newCachedThreadPool(),这个线程池从某种程度上来说不能算是线程池,我们来看方法源码:
class Executors {
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(
                0, // 核心线程数
                Integer.MAX_VALUE, // 最大线程数
                60L, TimeUnit.SECONDS, // 非核心线程空闲 60 秒就被回收
                // 任务缓冲队列
                // 一旦达到核心线程数,这个队列又不接受元素,就会开始创建非核心线程
                new SynchronousQueue<Runnable>()
                // 默认的拒绝策略:AbortPolicy,也就是直接报异常
                );
    }
}

为什么我说这不能算是线程池?

它的核心线程数设置为 0,而任务缓冲队列又是 SynchronousQueue,
也就是说一旦有任务到来,就直接创建非核心线程。一旦每个任务的执行时间都超过 60 秒,就会导致一直创建新线程。
而由于创建的都是非核心线程,所以一旦空闲,又会被全部回收销毁。
这也就失去线程池的价值,资源控制和减少创建销毁性能消耗

那这个线程有什么意义吗?

如果你真的要说意义,那就是可以用来运行非常短小的任务,比如一个任务就几秒的运行时间,
由于 60 秒才会回收空闲线程,所以线程可以不断重用,这时候它还像个线程池

  1. newFixedThreadPool(int nThreads),固定线程数量的线程池,还是来看方法源码:
class Executors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(
                nThreads, // 核心线程数
                nThreads, // 最大线程数
                0L, TimeUnit.MILLISECONDS, // 非核心线程空闲立马被回收
                // 任务缓存队列
                // 使用了不指定大小的 LinkedBlockingQueue 就意味着队列长度是 Integer.MAX_VALUE,
                // 所有任务太多就会占用很多的内存,也就有可能将内存耗尽,导致服务器崩溃
                new LinkedBlockingQueue<Runnable>()
                // 默认的拒绝策略:AbortPolicy,也就是直接报异常
                );
    }
}

我们可以留意到这个线程池的设置,核心线程数和最大线程数是一样的,也就是说队列满了,线程池就满了,
就不会创建非核心线程,所以这时候 0L, TimeUnit.MILLISECONDS 的设置相当于失效

  1. newSingleThreadExecutor(),单线程的线程池,废话不多说,上源码:
class Executors {
    public static ExecutorService newSingleThreadExecutor() {
         return new FinalizableDelegatedExecutorService
             (new ThreadPoolExecutor(
                     1, // 核心线程数
                     1, // 最大线程数
                     0L, TimeUnit.MILLISECONDS, // 非核心线程空闲立马被回收
                     // 任务缓存队列
                     // 使用了不指定大小的 LinkedBlockingQueue 就意味着队列长度是 Integer.MAX_VALUE,
                     // 所有任务太多就会占用很多的内存,也就有可能将内存耗尽,导致服务器崩溃
                     new LinkedBlockingQueue<Runnable>())
                     // 默认的拒绝策略:AbortPolicy,也就是直接报异常
                     );
    }
}

你可以把它当成是 newFixedThreadPool(1)

  1. newScheduledThreadPool(int corePoolSize),定时任务线程池
class Executors {
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
}

// 可以看到 ScheduledThreadPoolExecutor 的父类是 ThreadPoolExecutor
class ScheduledThreadPoolExecutor extends ThreadPoolExecutor
      implements ScheduledExecutorService {
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        // 下面的代码其实就是创建 ThreadPoolExecutor
         super(
                 corePoolSize, // 核心线程数
                 Integer.MAX_VALUE, // 最大线程数
                 0, NANOSECONDS, // 非核心线程空闲立马被回收
                 // 任务缓存队列
                 // 与 DelayQueue 类似
                 // 要求元素必须实现 java.util.concurrent.Delayed 接口
                 new DelayedWorkQueue()
                 // 默认的拒绝策略:AbortPolicy,也就是直接报异常
                 );
    }
}

定时任务线程池,可以说是 ThreadPoolExecutor 的子类,其实内部使用的队列是延迟队列,
这就意味着如果元素延迟时间还没到的话,就会阻塞,从而达到定时的效果。

这个线程池还可以定时间隔执行任务,它的原理其实很奇妙。就是把一个任务正常执行,然后判断它是否需要重复执行,
如果需要就把延迟时间更新为下一次执行的时间,再放回队列,这样就实现了重复间隔执行的效果

  1. newWorkStealingPool(int parallelism),会偷任务来做的线程池
class Executors {
    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool(parallelism,
                 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                 null, true);
    }
}

看了这么多内置线程池的源码,终于有一个是不一样的了。内部使用的是 ForkJoinPool 实现,
感兴趣的可以搜索来看

今天就到这里!晚安!
HFSS仿真的后处理结果,如何根据天线表面的电流密度分布对天线进行优化? 在HFSS仿真中,天线表面的Jsurf​是最直观、最有价值的诊断工具之一。它不仅告诉你天线“能不能工作”,还能告诉你“为什么工作”以及“哪里出了问题”。 阅读详情

相关推荐

瑞萨MCU定时器API实战:从Smart Configurator配置到中断与输入捕获应用

在嵌入式系统开发中,定时器(Timer)是实现精准时序控制、PWM输出和信号测量的核心硬件外设。其工作原理基于计数器在稳定时钟源驱动下递增或递减,达到预设值后触发中断或改变输出电平,从而为系统提供节拍和事件基准。通过图形化配置工具(如瑞萨的Smart Configurator),开发者可以高效地将复杂的硬件寄存器操作转化为清晰、标准化的C语言API函数,这极大地提升了开发效率并降低了出错风险。这种从硬件抽象到软件接口的技术价值在于,它使得开发者能更专注于应用逻辑,而非底层细节,尤其适用于工业控制、汽车电子等

weixin_42519733的博客 274

JAVA线程池

为什么要有线程池 当线程生存时间较短,且这种线程数量增多的时候,会反复创建销毁线程而增加大量开销。 创建线程池 ThreadPoolExecutor函数。 参数:(摘自LiuZh_) int corePoolSize =&gt; 该线程池中核心线程数最大值 核心线程: 线程池新建线程的时候,如果当前线程总数小于corePoolSize,则新建的是核心线程,如果超过cor...

zhaowh1993的博客 259

手把手教你理解MIS结构C-V特性曲线:从理论到测试实操

本文深入解析了金属-绝缘体-半导体(MIS)结构的电容-电压(C-V)特性曲线,从积累、耗尽到反型等物理状态出发,详细阐述了其测试原理与实操要点。文章重点介绍了如何通过C-V曲线提取氧化层厚度、掺杂浓度、界面态密度等关键参数,并探讨了偏压-温度(B-T)应力实验在揪出可动离子电荷等可靠性问题中的应用,为半导体器件物理研究与工艺评估提供了实用指南。

weixin_29304021的博客 441

手写ThreadPoolExecutor线程池

很多人不推荐造轮子,我偏不。我造轮子又不是为了上生产环境,而是为了加深理解,有何不可?私以为造轮子几乎是最好的学习方式,甚至没有之一。不了解设计,就无法把握整体。没看过代码,就无法完善细节。另外,从创作者的角度来说,直接分析源码有时太困难了,代码太多,抽象层次太深。如果可以通过造轮子,把抽象层次减少一些,采用平铺直叙的方式呈现,那么读者理解起来也就更容易些。既然造轮子这么好,那就,拿来吧你。今天带大家造一个线程池。

smart_an的专栏 154

别再只接个放大器了!压电传感器测量电路(电压/电荷放大器)的5个实战配置要点

本文深入解析压电传感器测量电路中的5个关键实战配置要点,包括电缆长度选择、输入阻抗匹配、过载保护设计、低频噪声抑制及放大器选型策略。特别针对电压放大器和电荷放大器的应用场景差异提供工程实践建议,帮助工程师有效解决信号失真、噪声干扰等常见问题,提升测量精度和系统可靠性。

weixin_26869081的博客 302

【SOC估计】基于EKF与二阶RC等效电路模型的锂电池SOC在线估计算法实现与仿真分析

本文详细介绍了基于扩展卡尔曼滤波(EKF)与二阶RC等效电路模型的锂电池SOC在线估计算法。通过Matlab仿真分析,展示了该算法如何实现高精度SOC估计,相比传统方法显著提升估计精度与鲁棒性,适用于电动汽车、储能系统等关键领域。

1095

Java线程池中的核心线程是如何被重复利用的?

真的!讲得太清楚了!https://blog.youkuaiyun.com/MingHuang2017/article/details/79571529 真的是解惑了   本文所说的“核心线程”、“非核心线程”是一个虚拟的概念,是为了方便描述而虚拟出来的概念,在代码中并没有哪个线程被标记为“核心线程”或“非核心线程”,所有线程都是一样的,只是当线程池中的线程多于指定的核心线程数量时,会将多出...

weixin_30318645的博客 306

用Python写个彩票小助手:自动生成双色球/大乐透号码并保存到桌面

本文介绍如何使用Python开发一个智能彩票助手,实现双色球和大乐透号码的随机生成与桌面文件保存功能。通过详细的代码示例,包括随机号码生成、文件操作、用户交互和错误处理,帮助Python初学者快速掌握实用工具开发技巧。

weixin_42566121的博客 515

SynchronousQueue解析上-TransferStack

Queue接口定义:[url]http://donald-draper.iteye.com/blog/2363491[/url] AbstractQueue简介:[url]http://donald-draper.iteye.com/blog/2363608[/url] ConcurrentLinkedQueue解析:[url]http://donald-draper.iteye.com/bl...

Donald_Draper 385

[QMT量化交易小白入门]-七十六、从tick数据中获取高频交易的量价背离信号

本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。

木头大左的博客 790

从数字后端角度谈谈occ电路(一)

摘要:本文介绍了芯片测试中OCC(On-Chip Clock Control)电路的设计与应用。随着工艺进步,芯片制造面临Stuck-at、Bridging和Delay等故障类型,需要不同时钟频率进行测试。OCC电路通过Clock Selection、Clock Chopping Control和Clock Gating三个模块,实现ATE时钟与PLL时钟的切换控制,支持慢速时钟检测Stuck-at故障和快速时钟检测Delay故障。文章详细解析了OCC电路结构及各模块功能,包括同步单元、移位寄存器等关键组件

芯冰乐 585

Java后端面试3天高效复习:核心考点与实战解析

Java作为企业级应用开发的核心语言,其技术体系涵盖从基础语法到分布式架构的完整知识栈。理解Java虚拟机内存模型、并发编程原理等底层机制,对于构建高性能、高可用的后端系统具有重要价值。在实际应用中,Spring框架的IoC容器和AOP编程模型大大提升了开发效率,而MySQL索引优化和Redis缓存策略则是保障系统性能的关键技术。随着微服务架构的普及,系统设计能力成为面试中的重要考察点。本文基于HashMap底层原理和线程池工作机制等高频考点,结合2026年最新面试趋势,为Java后端开发者提供一套可落地的

weixin_33827590的博客 465

【YoloV8改进策略】上采样改进|EUCB,轻量高效的上采样模块|即插即用

YOLOv8作为当前最先进的实时目标检测与实例分割模型之一,其在速度与精度之间取得了出色的平衡。然而,在资源受限的边缘设备或对实时性要求极高的应用场景中,YOLOv8的计算开销,尤其是在特征金字塔网络(FPN)和路径聚合网络(PAN)中用于特征融合的上采样操作,仍然是一个瓶颈。YOLOv8的颈部(Neck)结构中广泛使用nn.Upsample进行上采样,该操作虽然简单,但缺乏对特征内容的感知能力,且后续通常需要标准卷积来修复因插值带来的伪影,这增加了不必要的计算负担。

m0_47867638的博客 752

Java八股文智能复习系统:基于SmallThinker-3B-Preview的面试刷题伴侣

本文介绍了基于星图GPU平台,可自动化部署SmallThinker-3B-Preview镜像,快速搭建Java八股文智能复习系统。该系统能作为面试刷题伴侣,通过智能对话实现精准答题、深度追问与模拟面试,帮助开发者高效复习JVM、并发、Spring等核心知识点,提升面试准备效率。

weixin_35753431的博客 298

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

java面试八股文复习3

集合框架 List(线性结构) public interface List<E> extends Collection<E> {} 即有序的集合(也可以称作序列)。该接口的使用者可以精确地将控制每个元素在list中的插入位置。用户可以通过integer索引(即list中的位置)访问元素,并在list中搜索元素。 和集合(set)不同,list通常允许重复元素。即若list中存在a1,a2且a1.equals(a2)这在list中是被允许的。除了在set接口中有指定的规则,list接

weixin_45038271的博客 339

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java面试复习 Day 3

区域线程归属核心存储内容是否参与GC常见异常‌程序计数器‌私有指令地址否无‌虚拟机栈‌私有栈帧、局部变量否‌本地方法栈‌私有Native方法状态否‌堆‌共享对象实例、数组‌是 (核心)‌OOM‌方法区‌共享类元数据、常量、静态变量‌是 (少量)‌OOM口诀:‌对象存堆,局部变量存栈,类和静态放方法区,行号记在计数器,native方法走本地栈‌。‌‌。

lotus_csdn888的博客 179

Java面试复习 2021/3/22

子类,方法方法同步 如果父类中的某个方法使用了synchronized关键字,而子类中也覆盖了这个方法, 默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上synchronized关键字才可。 当然,也可以在子类中调用父类中相应的方法,这样虽然子类中的方法并不是同步的,但子类调用了父类中的同步方法,也就相当子类方法也同步了。 接口中的修饰的方法 接口中的方法默认都是public static final,这是JAVA8的规定。 构造函数只能被调用,不能被继承。 子类默..

Shapeofyou的博客 236

Java八股文智能复习:SmallThinker-3B-Preview模拟面试与深度解析

本文介绍了如何利用星图GPU平台,一键自动化部署SmallThinker-3B-Preview镜像,以构建一个智能的Java面试复习助手。该模型能够模拟真实面试场景,通过深度追问和主动出题,帮助开发者深入理解JVM、集合框架等核心八股文知识点,实现高效的互动式学习与查漏补缺。

weixin_36328210的博客 28

Java面试复习总结3——string和包装类

目录 String基础 Java String 类 创建字符串 StringDemo.java 文件代码: String基本用法 创建String对象的常用方法 String中常用的方法,用法如图所示,具体问度娘 三个方法的使用: lenth() substring() charAt() 字符串与byte数组间的相互转换 ==运算符和equals之间的区别: 字符串的不可变性...

Slayer_Zhao的博客 787

Java面试 2021-3-21复习

JAVA的运算符 算数运算符、关系运算符、逻辑运算符、位运算符 算数运算符(9):+ - * / % ++ -- 关系运算符(6):== != > >= < <= 逻辑运算符(6):&& || ! ^ &(按位与) | 位运算符(7):& | ~ ^ >> << >>>; 注意: 实际含义不同: “||”:如果左边计算后的操作数为true,右边则...

Shapeofyou的博客 122

Java面试复习(3)之IO流

IO流(Input Output)

i_nclude的博客 315

Java后端面试3天高效复习指南:核心知识点与实战技巧

Java作为企业级应用开发的核心语言,其技术生态涵盖从基础语法到分布式系统设计的广泛领域。理解Java虚拟机(JVM)的内存管理机制和垃圾回收原理,是优化应用性能的关键;而并发编程中的线程池配置与锁机制,则直接影响高并发场景下的系统稳定性。结合MySQL索引优化与Redis缓存技术,能够有效提升数据读写效率,解决缓存穿透、击穿等典型问题。Spring框架通过IOC和AOP实现了组件解耦与功能增强,而Spring Boot的自动配置机制进一步简化了企业级应用的开发部署。这些技术共同支撑了电商秒杀、实时数据处理

weixin_30938149的博客 539

2026年Java后端面试核心考点与3天高效复习策略

Java并发编程是后端开发的核心技术之一,其原理基于多线程协同处理任务以提升系统吞吐量。通过理解线程生命周期、锁机制和内存模型,开发者能够编写出高效且线程安全的代码。这项技术的价值在于充分利用多核CPU资源,应对高并发场景下的性能挑战。在实际应用中,Java并发广泛用于电商秒杀、实时数据处理等业务场景。本文结合线程池和synchronized等热词,深入探讨面试中常见的并发问题解决方案,帮助求职者快速掌握核心考点。

weixin_30915275的博客 307

Java面试 2021/3/20复习

1.File类对象代表:一个文件或一个文件目录。Java程序表示一个文件或目录,必须有个File对象。但有File对象不一定有真实的文件或目录存在。 2.File类不能进行对文件进行的输入和输出操作(使用IO流才行)。 3. ...

Shapeofyou的博客 104

Java后端面试3天高效复习指南:从核心考点到实战技巧

Java作为企业级应用开发的核心语言,其底层原理和工程实践是后端开发者的必备基础。理解Java集合框架的线程安全机制、JVM内存模型和垃圾回收原理,能够帮助开发者编写高性能、可扩展的应用程序。在分布式系统中,MySQL索引优化和Redis缓存技术尤为重要,它们直接影响系统的响应速度和数据一致性。通过掌握这些核心技术,开发者可以应对高并发场景下的数据存储与缓存挑战,例如电商秒杀系统的库存扣减和缓存穿透问题。本文基于Java并发编程和Redis实战经验,提供了一套3天高效复习方案,帮助面试者快速梳理技术脉络,将

weixin_33875564的博客 397

挑战Java面试题复习第3天,无人扶我青云志

无人扶我青云志,我自踏雪至山巅

专注编程和人工智能! 791

java short 赋值_一道Java面试题的101℃思考

在java学员去公司面试的时候,经常会遇到下面这样类似的一些面试题:Œshort s1 = 1; s1 = s1+1;能正常运行吗? short s1 = 1; s1 += 1;呢?byte s1 = 1; s1 = s1+1;有错吗? byte s1 = 1; s1 += 1;有错吗?Žint s1 = 1; s1 = s1+1;能正常运行吗? int s1 = 1; s1 += 1;呢?l...

weixin_39857876的博客 347
上一篇: Java 面试复习_2
下一篇: Java 面试复习_4
水不要鱼
博客等级 码龄7年 7粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值