【面试手撕】非常规算法,多线程常见手撕题目
【面试手撕】非常规算法,多线程常见手撕题目
- 生产者消费者
- ReentrantLock实现的生产苹果/消费苹果
- synchronized实现的生产消费
- LinkedBlockingQueue阻塞队列方法实现
- 多条件资源分配
- 分布式任务调度模拟
- 交替打印
- 两个线程交替打印1-100之间的数
- ReentrantLock 实现
- synchronized实现
- Semaphore实现
- 三个线程交替打印1-100之间的数
- ReentrantLock
- Synchronized
- Semaphore
- 线程池
- 手写线程池
- 使用线程池实现任务
- **机场安检模拟(现实场景)**
生产者消费者
ReentrantLock实现的生产苹果/消费苹果
仓库类:
- 定义最大苹果数量+当前苹果数量
- 生产/消费方法
无非是,先判断条件是否满足,不满足就调用await等待,满足的话生产/消费苹果,之后调用signal唤醒其他线程。
注意用的是条件变量,full,empty
生产的时候,仓库满了调用full.await()等待,生产后,调用empty.signal()唤醒消费者。消费是时候相反即可。
最后,注意try,catch,finally 在finally中实现解锁。
package Others.JUC;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;public class ProducerConsumerDemo1 {public static void main(String[] args) {// 1.初始化3个生产者线程Storage storage = new Storage();for(int i = 0;i<3;i++){new Thread(new Producer(storage),"生产者"+i).start();}// 2.初始化2个消费者线程for(int i = 0;i<2;i++){new Thread(new Consumer(storage),"消费者"+i).start();}}
}class Storage{private int capacity = 10 ;// 最多容纳10个苹果private int count = 0; // 当前苹果数量private ReentrantLock lock = new ReentrantLock();private Condition full = lock.newCondition();private Condition empty = lock.newCondition();public void produce() throws InterruptedException {try{lock.lock();// 生产苹果while(count>=capacity){full.await();}count++;System.out.println(Thread.currentThread().getName()+" 生产了一个苹果,当前苹果数量:"+count);empty.signal();}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}TimeUnit.SECONDS.sleep(1); // 模拟生产苹果的时间}public void consume() throws InterruptedException {try{lock.lock();// 条件不满足,等待while(count<=0){empty.await();}count--;System.out.println(Thread.currentThread().getName()+" 消费了一个苹果,当前苹果数量:"+count);full.signal();}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}TimeUnit.SECONDS.sleep(1); // 模拟消费苹果的时间}
}class Producer implements Runnable{private Storage storage;public Producer(Storage storage){this.storage = storage;}public Producer(){}@Overridepublic void run() {while(true){try{Thread.sleep(1000); // 模拟生产苹果的时间,1秒生产一个苹果storage.produce();}catch (InterruptedException e){e.printStackTrace();}}}
}class Consumer implements Runnable{private Storage storage;public Consumer(Storage storage){this.storage = storage;}public Consumer(){}@Overridepublic void run() {while(true){try{Thread.sleep(1000); // 模拟消费苹果的时间,1秒消费一个苹果storage.consume();}catch (InterruptedException e){e.printStackTrace();}}}
}
synchronized实现的生产消费
核心是用synchronized锁住了,由于synchronized可以锁随便一个Object,所以把缓冲区buffer作为synchronized锁住的对象即可。
这里主要的区别就是Storage的实现不一致。其他的一致。
class Storage{// 缓冲区private LinkedList<Object> buffer = new LinkedList<>();// 缓冲区大小private final int MAX_SIZE = 10;public void produce(){synchronized(buffer){while(buffer.size()+1>MAX_SIZE){System.out.println("缓冲区已满,生产者等待");try{buffer.wait();}catch(InterruptedException e){e.printStackTrace();}}buffer.add(new Object());System.out.println("生产者生产一个产品,当前缓冲区大小为"+buffer.size());buffer.notify();}}public void consume(){synchronized(buffer){while(buffer.size()==0){System.out.println("缓冲区为空,消费者等待");try{buffer.wait();}catch(InterruptedException e){e.printStackTrace();}}buffer.remove();System.out.println("消费者消费一个产品,当前缓冲区大小为"+buffer.size());buffer.notify();}}
}class Producer implements Runnable{private Storage storage;public Producer(Storage storage){this.storage = storage;}public Producer(){}@Overridepublic void run() {while(true){try{Thread.sleep(1000); // 模拟生产苹果的时间,1秒生产一个苹果storage.produce();}catch (InterruptedException e){e.printStackTrace();}}}
}
LinkedBlockingQueue阻塞队列方法实现
这里更简单了,不需要手动加锁。只需要使用put/take方法,会自己阻塞
class Storage{LinkedBlockingQueue<Object> buffer = new LinkedBlockingQueue<>(10);public void produce(){try{buffer.put(new Object());System.out.println(Thread.currentThread().getName()+" 生产了一个苹果,当前苹果数量:"+buffer.size());} catch (InterruptedException e) {throw new RuntimeException(e);}}public void consume(){try{buffer.take();System.out.println(Thread.currentThread().getName()+" 消费了一个苹果,当前苹果数量:"+buffer.size());} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
多条件资源分配
场景: 某工厂需要组装产品,要求:
- 零件A和零件B必须同时存在才能组装
- 仓库最多存放5个A和5个B
- 2个供应商线程分别生产A/B(随机0.5~1秒生产1个)
- 3个组装线程消耗1A+1B组合(每次组装耗时1秒)
要求: 使用 wait/notifyAll
实现资源协调,避免死锁
public class FactoryAssembly {private int partA = 0;private int partB = 0;private final int MAX_PARTS = 5;private int assembledProducts = 0;public static void main(String[] args) {FactoryAssembly factory = new FactoryAssembly();// 创建供应商线程AThread supplierA = new Thread(() -> {try {while (true) {factory.producePartA();// 随机生产时间 0.5-1秒Thread.sleep(500 + (long)(Math.random() * 500));}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});// 创建供应商线程BThread supplierB = new Thread(() -> {try {while (true) {factory.producePartB();// 随机生产时间 0.5-1秒Thread.sleep(500 + (long)(Math.random() * 500));}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});// 创建3个组装线程for (int i = 1; i <= 3; i++) {final int assemblyLineId = i;Thread assemblyLine = new Thread(() -> {try {while (true) {factory.assembleParts(assemblyLineId);// 组装时间1秒Thread.sleep(1000);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});assemblyLine.start();}supplierA.start();supplierB.start();}// 生产零件Apublic synchronized void producePartA() throws InterruptedException {// 如果A零件已达到上限,等待while (partA >= MAX_PARTS) {System.out.println("零件A仓库已满,供应商A等待中...");wait();}partA++;System.out.println("供应商A生产了一个零件A,当前库存: A=" + partA + ", B=" + partB);// 通知所有等待的线程notifyAll();}// 生产零件Bpublic synchronized void producePartB() throws InterruptedException {// 如果B零件已达到上限,等待while (partB >= MAX_PARTS) {System.out.println("零件B仓库已满,供应商B等待中...");wait();}partB++;System.out.println("供应商B生产了一个零件B,当前库存: A=" + partA + ", B=" + partB);// 通知所有等待的线程notifyAll();}// 组装产品public synchronized void assembleParts(int lineId) throws InterruptedException {// 如果A或B零件不足,等待while (partA < 1 || partB < 1) {System.out.println("组装线 #" + lineId + " 等待零件,当前库存: A=" + partA + ", B=" + partB);wait();}// 消耗零件A和B各一个partA--;partB--;assembledProducts++;System.out.println("组装线 #" + lineId + " 完成一个产品组装! 总计: " + assembledProducts + ",剩余库存: A=" + partA + ", B=" + partB);// 通知所有等待的线程notifyAll();}
}
分布式任务调度模拟
题目5:分布式任务调度模拟(综合)
需求:
- 主节点(Producer)每隔1秒生成一个带优先级的任务
- 3个工作节点(Consumer)从任务队列获取任务执行
- 高优先级任务(如优先级>5)必须立即抢占执行
- 使用
PriorityBlockingQueue
实现任务队列 - 任务执行时间随机(1~3秒)
import java.util.concurrent.*;public class DistributedTaskScheduler {// 定义任务类static class Task implements Comparable<Task> {private final int id;private final int priority;private final int executionTime;public Task(int id, int priority) {this.id = id;this.priority = priority;// 随机执行时间 1-3秒this.executionTime = 1000 + (int)(Math.random() * 2000);}public int getId() {return id;}public int getPriority() {return priority;}public int getExecutionTime() {return executionTime;}// 优先级比较,高优先级的任务排在前面@Overridepublic int compareTo(Task other) {return other.priority - this.priority;}@Overridepublic String toString() {return "Task #" + id + " (优先级: " + priority + ")";}}public static void main(String[] args) {// 使用优先级队列存储任务PriorityBlockingQueue<Task> taskQueue = new PriorityBlockingQueue<>();// 创建锁对象用于高优先级任务抢占Object preemptionLock = new Object();// 任务计数器final int[] taskCounter = {0};// 主节点线程生成任务Thread producer = new Thread(() -> {try {while (true) {// 生成随机优先级 (1-10)int priority = 1 + (int)(Math.random() * 10);Task task = new Task(++taskCounter[0], priority);taskQueue.put(task);System.out.println("主节点生成: " + task);// 如果是高优先级任务,通知工作节点抢占if (priority > 5) {System.out.println("!!!! 高优先级任务 #" + task.getId() + " (优先级: " + priority + ") 需要抢占执行!");synchronized (preemptionLock) {preemptionLock.notifyAll();}}// 每隔1秒生成一个任务Thread.sleep(1000);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});// 创建3个工作节点线程for (int i = 1; i <= 3; i++) {final int workerId = i;Thread consumer = new Thread(() -> {try {while (true) {// 从队列获取任务Task task = taskQueue.take();System.out.println("工作节点 #" + workerId + " 开始执行: " + task);// 模拟任务执行Thread.sleep(task.getExecutionTime());System.out.println("工作节点 #" + workerId + " 完成任务: " + task);// 检查是否有高优先级任务需要执行if (!taskQueue.isEmpty() && taskQueue.peek().getPriority() > 5) {System.out.println("工作节点 #" + workerId + " 发现高优先级任务,立即处理!");} else {// 如果没有高优先级任务,稍微休息一下synchronized (preemptionLock) {try {preemptionLock.wait(500);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});consumer.start();}producer.start();}
}
交替打印
两个线程交替打印1-100之间的数
ReentrantLock 实现
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TwoThreadsReentrantLock {private static volatile int num = 1;private static final int MAX = 100;private static Lock lock = new ReentrantLock();private static Condition cA = lock.newCondition();private static Condition cB = lock.newCondition();public static void main(String[] args) {new Thread(()->{while(num<MAX){try{lock.lock();while(num%2==0){cA.await();}System.out.println(Thread.currentThread().getName()+" "+num++);cB.signal();}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}}},"线程A").start();new Thread(()->{while(num<MAX){try{lock.lock();while(num%2!=0){cB.await();}System.out.println(Thread.currentThread().getName()+" "+num++);cA.signal();}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}}},"线程B").start();}
}
synchronized实现
public class TwoThreadsSynchronized {private static volatile int num = 1;private static final int MAX = 100;private static final Object lock = new Object();public static void main(String[] args) {new Thread(()->{while(num<MAX){synchronized(lock){while(num%2==0){try{lock.wait();}catch (InterruptedException e){e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+" "+num++);lock.notify();}}},"t1").start();new Thread(()->{while(num<MAX){synchronized(lock){while(num%2==1){try{lock.wait();}catch (InterruptedException e){e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+" "+num++);lock.notify();}}},"t2").start();}
}
Semaphore实现
import java.util.concurrent.Semaphore;public class TwoThreadsSemaphore {private static volatile int num = 1;private static final int MAX = 100;private static Semaphore s1 = new Semaphore(1);private static Semaphore s2 = new Semaphore(0);public static void main(String[] args) {new Thread(()->{while(num<MAX){try{s1.acquire();}catch (InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+" "+num++);s2.release();}},"t1").start();new Thread(()->{while(num<MAX){try{s2.acquire();}catch (InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+" "+num++);s1.release();}},"t2").start();}
}
三个线程交替打印1-100之间的数
ReentrantLock
public class ThreeThreadReentrantLock {static class PrintTask{private static volatile int num = 1;private static final int MAX = 100;private static Lock lock = new ReentrantLock();private static Condition cA = lock.newCondition();private static Condition cB = lock.newCondition();private static Condition cC = lock.newCondition();public void print1(){while(num<=MAX){try{lock.lock();while(num%3!=1){cA.await();}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);cB.signal();}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}}}public void print2(){while(num<=MAX){try{lock.lock();while(num%3!=2){cB.await();}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);cC.signal();}catch (InterruptedException e){e.printStackTrace();}}}public void print3(){while(num<=MAX){try{lock.lock();while(num%3!=0){cC.await();}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);cA.signal();}catch (InterruptedException e){e.printStackTrace();}}}}public static void main(String[] args) {PrintTask task = new PrintTask();new Thread(task::print1,"线程A").start();new Thread(task::print2,"线程B").start();new Thread(task::print3,"线程C").start();}
}
Synchronized
public class ThreeThreadSynchronized {static class PrintTask{private static volatile int num = 1;private static final int MAX = 100;private static final Object lock = new Object();private boolean isA = true;private boolean isB = false;private boolean isC = false;public void print1(){while(num<=MAX){synchronized(lock){while(!isA){try{lock.wait();}catch (InterruptedException e){e.printStackTrace();}}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);isA = false;isB = true;lock.notifyAll();}}}public void print2(){while(num<=MAX){synchronized(lock){while(!isB){try{lock.wait();}catch (InterruptedException e){e.printStackTrace();}}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);isB = false;isC = true;lock.notifyAll();}}}public void print3(){while(num<=MAX){synchronized(lock){while(!isC){try{lock.wait();}catch (InterruptedException e){e.printStackTrace();}}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);isC = false;isA = true;lock.notifyAll();}}}}public static void main(String[] args) {PrintTask task = new PrintTask();new Thread(task::print1,"线程A").start();new Thread(task::print2,"线程B").start();new Thread(task::print3,"线程C").start();}
}
Semaphore
import java.util.concurrent.Semaphore;public class ThreeThreadSemaphore {static class PrintTask{private static volatile int num = 1;private static final int MAX = 100;private static Semaphore s1 = new Semaphore(1);private static Semaphore s2 = new Semaphore(0);private static Semaphore s3 = new Semaphore(0);public void print1(){while(num<=MAX){try{s1.acquire();}catch (InterruptedException e){e.printStackTrace();}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);s2.release();}}public void print2(){while(num<=MAX){try{s2.acquire();}catch (InterruptedException e){e.printStackTrace();}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);s3.release();}}public void print3(){while(num<=MAX){try{s3.acquire();}catch (InterruptedException e){e.printStackTrace();}if(num>MAX){break;}System.out.println(Thread.currentThread().getName()+" "+num++);s1.release();}}}public static void main(String[] args) {PrintTask task = new PrintTask();new Thread(task::print1,"t1").start();new Thread(task::print2,"t2").start();new Thread(task::print3,"t3").start();}}
线程池
手写线程池
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;public class CustomThreadPool {private final BlockingQueue<Runnable> taskQueue;private final List<WorkerThread> workers;private final AtomicBoolean isShutdown;private final int corePoolSize;private final AtomicInteger threadCount;public CustomThreadPool(int corePoolSize) {this.corePoolSize = corePoolSize;this.taskQueue = new LinkedBlockingQueue<>();this.workers = new ArrayList<>(corePoolSize);this.isShutdown = new AtomicBoolean(false);this.threadCount = new AtomicInteger(0);// 初始化线程池中的工作线程for (int i = 0; i < corePoolSize; i++) {WorkerThread worker = new WorkerThread("Worker-" + i);workers.add(worker);worker.start();}}// 提交任务到线程池public void execute(Runnable task) {if (isShutdown.get()) {throw new IllegalStateException("线程池已关闭,无法接受新任务");}try {taskQueue.put(task);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}// 关闭线程池public void shutdown() {isShutdown.set(true);// 中断所有工作线程for (WorkerThread worker : workers) {if (!worker.isInterrupted()) {worker.interrupt();}}}// 等待所有任务完成public void awaitTermination() throws InterruptedException {for (WorkerThread worker : workers) {worker.join();}}// 获取当前队列中等待的任务数public int getQueueSize() {return taskQueue.size();}// 获取活跃线程数public int getActiveThreadCount() {return threadCount.get();}// 工作线程类private class WorkerThread extends Thread {public WorkerThread(String name) {super(name);}@Overridepublic void run() {while (!isShutdown.get() || !taskQueue.isEmpty()) {try {// 从队列中获取任务Runnable task = taskQueue.poll();if (task != null) {threadCount.incrementAndGet();try {System.out.println(Thread.currentThread().getName() + " 开始执行任务");task.run();System.out.println(Thread.currentThread().getName() + " 完成任务");} finally {threadCount.decrementAndGet();}} else {// 如果队列为空,等待新任务Thread.sleep(100);}} catch (InterruptedException e) {// 线程被中断,结束循环break;} catch (Exception e) {// 任务执行中的异常不应该影响工作线程System.err.println(Thread.currentThread().getName() + " 执行任务时发生异常: " + e.getMessage());}}System.out.println(Thread.currentThread().getName() + " 退出");}}// 测试自定义线程池public static void main(String[] args) throws InterruptedException {// 创建一个有3个线程的线程池CustomThreadPool threadPool = new CustomThreadPool(3);// 提交10个任务for (int i = 0; i < 10; i++) {final int taskId = i;threadPool.execute(() -> {try {System.out.println("执行任务 #" + taskId);// 模拟任务执行时间Thread.sleep(1000);System.out.println("任务 #" + taskId + " 执行完成");} catch (InterruptedException e) {Thread.currentThread().interrupt();}});}// 等待5秒后关闭线程池Thread.sleep(5000);System.out.println("关闭线程池");threadPool.shutdown();// 等待所有任务完成threadPool.awaitTermination();System.out.println("所有任务已完成,程序退出");}
}
使用线程池实现任务
机场安检模拟(现实场景)
场景:
- 3个安检口(线程)同时工作
- 旅客(任务)以随机间隔(0~2秒)到达,加入队列
- 每个安检需要2秒处理时间
- 使用
ExecutorService
线程池实现
扩展要求:
- 显示实时排队人数
- 当排队超过10人时增加1个临时安检口
- 使用
ThreadPoolExecutor
动态调整
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;public class SecurityCheckSimulation {// 旅客计数器private static final AtomicInteger passengerCount = new AtomicInteger(0);// 队列中等待的旅客数量private static final AtomicInteger waitingCount = new AtomicInteger(0);// 安检口初始数量private static int initialCheckpoints = 3;// 安检口最大数量private static int maxCheckpoints = 4;public static void main(String[] args) {// 创建可调整大小的线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(initialCheckpoints, // 核心线程数maxCheckpoints, // 最大线程数60L,TimeUnit.SECONDS, // 线程空闲时间new LinkedBlockingQueue<>(), // 任务队列new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略);// 模拟旅客到达Thread passengerGenerator = new Thread(()->{try{while(true){// 新旅客到达int passengerId = passengerCount.incrementAndGet();waitingCount.incrementAndGet();System.out.println("Passenger " + passengerId + " 到达安检。当前排队人数:"+waitingCount.get());// 动态调整安检口数量if(waitingCount.get()>10 && executor.getCorePoolSize()<maxCheckpoints){executor.setCorePoolSize(maxCheckpoints);System.out.println("===== 排队人数过多,增加临时安检口! 当前安检口: "+executor.getCorePoolSize()+"=====");}// 将旅客提交给安检口executor.submit(()->processPassenger(passengerId));// 模拟旅客到达的随机时间间隔,随机等待0-2秒Thread.sleep((long) (Math.random()*2000));}}catch (InterruptedException e){e.printStackTrace();}});passengerGenerator.start();}private static void processPassenger(int passengerId) {// 模拟安检过程System.out.println("Passenger " + passengerId + " 正在安检...");// 安检耗时2秒try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("Passenger " + passengerId + " 安检完成。");waitingCount.decrementAndGet();System.out.println("当前排队人数:"+waitingCount.get());}
}
相关文章:
【面试手撕】非常规算法,多线程常见手撕题目
【面试手撕】非常规算法,多线程常见手撕题目 生产者消费者ReentrantLock实现的生产苹果/消费苹果synchronized实现的生产消费LinkedBlockingQueue阻塞队列方法实现多条件资源分配分布式任务调度模拟 交替打印两个线程交替打印1-100之间的数ReentrantLock 实现synchr…...
MySQL复合查询
目录 多表查询 自连接 子查询 单行子查询 多行子查询 in关键字 all关键字 any关键字 多列子查询 from中使用子查询 合并查询 union 操作符 union all 操作符 内外连接 内连接 外连接 左外连接 右外连接 前几期我们已经学习了MySQL的基本查询&…...
登录Xshell主机及Linux基本指令
✅博客主页:爆打维c-CSDN博客 🐾 🔹分享c、c知识及代码 🐾 🔹Gitee代码仓库 五彩斑斓黑1 (colorful-black-1) - Gitee.com 一、操作系统简介 Linux其实跟我们熟知的Window一样,它们都是操作系统。 &#x…...
[LevelDB]关于LevelDB存储架构到底怎么设计的?
本文内容组织形式 LevelDB 存储架构重要特点总体概括LevelDB中内存模型MemTableMemTable的数据结构背景:SkipListSkiplist的数据结构 Skiplist的数据访问细节 SkipList的核心方法Node细节源代码 MemTable的数据加速方式Iterator 的核心方法 MemTable 的读取&写入…...
深入解析 React Diff 算法:原理、优化与实践
深入解析 React Diff 算法:原理、优化与实践 1. 引言 React 作为前端领域的标杆框架,采用 虚拟 DOM(Virtual DOM) 来提升 UI 更新性能。React 的 Diff 算法(Reconciliation) 是虚拟 DOM 运行机制的核心&a…...
【从零开始】Air780EPM的LuatOS二次开发——OneWire协议调试注意事项!
当涉及到与传感器、执行器等外部设备交互时,OneWire协议的高效调试成为决定项目成败的关键环节。OneWire协议(单总线协议)以其仅需一根数据线即可实现设备通信的极简特性,被广泛应用于温度传感器、身份识别模块等场景。 一、LuatO…...
响应(Response)
在 Flask 中,视图函数可以返回多种类型的响应,例如字符串、HTML、JSON、文件等。Flask 提供了 make_response 函数,用于生成和自定义 HTTP 响应。 2.1 默认响应 默认情况下,视图函数返回的字符串会被 Flask 包装成一个 HTTP 响应…...
C++学习之云盘项目fastDFS
1.资料介绍 1.1 一些概念 1. 什么是服务器 硬件 : 一台配置高的电脑 软件 : 电脑必须有一个能够解析 http 协议的软件 2. 常见的 Web 服务器 tomcat 服务器 apache 组织产品 , 开源的免费服务器 weblogic 服务器 bea 公司 , 收费的服务器 不交费 , 访问量受限…...
使用vue3+el-form实现动态新增名称,值,并对名称进行必填校验
使用vue3el-form实现动态新增名称,值,并对名称进行必填校验 效果图 代码 <template><el-form :model"form" :rules"rules" ref"dynamicForm"><!-- 动态添加的名称和值 --><el-row v-for"(ite…...
Spring Boot 集成高德地图电子围栏
摘要:本文手把手教你通过 Spring Boot 调用高德地图 API 实现电子围栏功能,涵盖云端围栏创建、设备位置监控与本地算法校验,附带完整代码和避坑经验! 一、电子围栏核心原理 1.1 什么是电子围栏? 虚拟地理边界&#x…...
3.JVM-内部结构
栈结构 动态链接 栈中的对象指向堆中的实际引用 符号引用: 比如一个类的名称 直接引用: 具体堆中数据信息 方法返回 栈中上一层的结果和下一层的指令 操作数栈 局部变量 该线程中需要的变量 PC计数器 程序计数器:存当前执行到那一步 操作数栈里面将计算完之后的结果推入局…...
Spring 框架中常用注解和使用方法
Spring 框架中常用注解的详细解释与应用场景,结合核心功能和实际开发需求进行分类说明: 1.组件定义注解 1.1 Component 作用:通用注解,将普通 Java 类标记为 Spring 管理的 Bean,由容器实例化和管理,相当…...
神策数据接入 DeepSeek,AI 赋能数据分析与智能运营
在 AI 技术迅猛发展的浪潮下,神策数据正在加速推进人工智能在数据分析和智能运营领域的深度应用。近日,神策数据宣布全面接入 DeepSeek,为企业客户带来更加智能化、高效的数据分析与智能运营服务。这一举措展现了神策数据在人工智能方向的探索…...
微软OneNote无法同步解决方案
目录 前言原因UWP特性 解决方案C***h注册表 参考链接 前言 假设有多台Windows电脑,最方便且免费的多设备笔记同步方案就是微软自家的OneNote,使用OneDrive自带的5G云存储。 但是在国内大陆的OneNote,经常会出现无法同步、同步失败࿱…...
一般机器学习有哪些算法?
传统的机器学习算法主要依赖统计学和优化方法,不依赖深层神经网络,通常具有较高的可解释性且适用于中小规模数据集。以下是经典的传统机器学习算法分类及代表性模型: 一、监督学习(Supervised Learning) 1. 回归&…...
RAGFlow部署与使用(开源本地知识库管理系统,包括kibana配置)
一、RAGFlow 简介 戳我访问RAGFlow RAGFlow 是一款基于深度文档理解构建的开源 RAG(Retrieval-Augmented Generation)引擎。它可以给我们搭建本地知识库,将用户的知识文档上传到RAGFlow后,通过文档切分、向量入库,在…...
STM32G070CBT6读写FLASH中的数据
向FLASH中写入数据函数 /*函数说明:向FLASH中写数据形参:addr-要写入数据的起始地址 data-准备写入数据 len-数据大小返回值:1-成功,0-失败 */ uint8_t FlashWriteData(uint64_t addr,uint8_t data[],size_t len) {uint32_t Fir…...
如何使用HACS一键集成米家与果家设备到HomeAssistant玩转智能家居
文章目录 前言1. 下载HACS源码2. 添加HACS商店3. 绑定米家设备 前言 各位科技潮人和智能家居发烧友们,是不是也梦想着把家里变成一个高科技的空间?有了群晖NAS这位得力助手,不仅存储空间大得吓人,还能通过Docker轻松安装各种应用…...
Flutter_学习记录_状态管理之GetX
1. 状态管理、Flutter Getx介绍 1.1 状态管理 通俗的讲:当我们想在多个页面(组件/Widget)之间共享状态(数据),或者一个页面(组件/Widget)中的多个子组件之间共享状态(数…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_09自定义单元格的固定表头表格
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_09自定义单元格…...
基于 Prometheus + Grafana 监控微服务和数据库
以下是基于 Prometheus Grafana 监控微服务和数据库的详细指南,包含架构设计、安装配置及验证步骤: 一、整体架构设计 二、监控微服务 1. 微服务指标暴露 Spring Boot 应用: xml <!-- 添加 Micrometer 依赖 --> <dependency>…...
文件解析漏洞
一,IIS解析漏洞 1,IIS6.X 目录解析 在iis的⽹站根⽬录新建⼀个名为q.asp的⽂件,在q.asp中新建⼀个txt⽂件 在外部浏览器中访问windows2003的iis⽹站中的1.txt 发现asp代码被执⾏ 2,IIS6.X 畸形文件解析 在iis的⽹站根⽬录新建⼀…...
C++学习笔记(二十一)——文件读写
一、文件读写 作用: 文件读写指的是将数据从程序存储到文件,或从文件读取数据,以实现数据的持久化存储。 C 提供了 fstream 头文件,用于文件操作,主要包括: ofstream(输出文件流)—…...
Ubuntu上部署Flask+MySQL项目
一、服务器安装python环境 1、安装gcc(Ubuntu默认已安装) 2、安装python源码 wget https://www.python.org/ftp/python/3.13.2/Python-3.13.2.tar.xz 3、安装Python依赖库 4、配置python豆瓣源 二、服务器安装虚拟环境 1、安装virtualenv pip3.10 ins…...
Unity WebGL项目访问时自动全屏
Unity WebGL项目访问时自动全屏 打开TemplateData/style.css文件 在文件最下方添加红色框内的两行代码 使用vscode或者其他编辑器打开index.html 将按钮注释掉,并且更改为默认全屏...
C#RTSP代理推流程序
将不支持rtsp的相机通过rtspserver实现推流 主要功能 1. rtsp交互 2. udp推流 3. Bitmap转H264,RTP打包 4. 支持多路播放...
Redis--渐进式遍历
目录 一、引言 二、介绍 三、命令 四、总结 一、引言 本篇文章将介绍Redis中的渐进式遍历 二、介绍 一般使用keys * 来获取所有的key,但这样的操作如果数据量很大的时候,会将服务器给卡死,所以通过渐进式遍历,就会避免这个问题…...
PyTorch深度学习框架60天进阶学习计划 - 第23天:Transformer架构解析
让我继续完成机器翻译示例的代码: PyTorch深度学习框架60天进阶学习计划:第23天 Transformer架构解析 学习目标 推导自注意力机制数学公式详解位置编码的傅里叶基函数设计对比编码器-解码器结构的信息流动差异 1. Transformer架构概述 Transformer架…...
《C#上位机开发从门外到门内》3-4:基于TCP/IP的远程监控系统设计与实现
文章目录 一、项目概述二、系统架构设计三、通信协议设计四、功能模块实现五、系统安全性与稳定性六、性能优化与测试七、实际应用案例八、结论 随着信息技术的飞速发展,远程监控系统在工业自动化、智能家居、环境监测等领域的应用日益广泛。基于TCP/IP协议的远程监…...
【MySQL】MySQL审计工具Audit Plugin安装使用
MySQL审计工具Audit Plugin安装使用 https://www.cnblogs.com/waynechou/p/mysql_audit.html MySQL 5.6 开启审计功能 https://blog.51cto.com/u_15127556/4344503 MySQL之添加日志审计功能 https://blog.csdn.net/weixin_43279032/article/details/105507170 MySQL开启日志记录…...
Flutter 按钮组件 ElevatedButton 详解
目录 1. 引言 2. ElevatedButton 的基本用法 3. 主要属性 4. 自定义按钮样式 4.1 修改背景颜色和文本颜色 4.2 修改按钮形状和边框 4.3 修改按钮大小 4.4 阴影控制 4.5 水波纹效果 5. 结论 相关推荐 1. 引言 在 Flutter 中,ElevatedButton 是一个常用的…...
AndroidStudio+Android8.0下的Launcher3 导入,编译,烧录,调试
文章目录 编译完成搜索输出文件Android.mk配置gradle编译环境报错一报错二报错三输出文件下载INSTALL_FAILED_TEST_ONLY查找系统签名查找签名工具开始签名查看签名签名问题重新生成秘钥解决方案生成成功挽救错误:重新刷机更换testkey秘钥keystore生成keystoreINSTALL_FAILED_S…...
【差分约束】P5590 赛车游戏|省选-
本文涉及知识点 【数学 线性代数】差分约束 P5590 赛车游戏 题目描述 R 君和小伙伴打算一起玩赛车。但他们被老司机 mocania 骗去了秋名山。 秋名山上有 n n n 个点和 m m m 条边,R 君和他的小伙伴要从点 1 1 1 出发开往点 n n n,每条边都有一个…...
咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包
咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包(内有教程) 刷机教程简单说明: 1、把下载好的刷机包,U盘里建立一个upgrade文件夹,固件放入此文件夹里,放入U盘中,注意升级包为压缩包不要对…...
【软件工程】06_软件设计
6.1 软件设计概述 1. 软件设计的目标 软件设计的最基本目标就是回答 “概括地描述系统如何实现用户所提出来的功能和性能等方面的需求?” 这个问题。 软件设计的目标是根据软件需求分析的结果,设想并设计软件,即根据目标系统的逻辑模型确定目标系统的物理模型。包括软件体系…...
在Flutter中使用Future读取一个大文件会导致线程阻塞吗
目录 一、Future 与文件读取的机制 1. Dart 的异步 I/O 原理 2. 代码示例 二、什么情况下会阻塞主线程? 1. I/O 操作本身不会阻塞 2. 数据处理可能阻塞 3. 示例对比 三、如何避免阻塞主线程? 1. 将耗时操作移到 Isolate 2. 使用 compute 函数(简化 Isolate 操作)…...
2025-03-17 Unity 网络基础1——网络基本概念
文章目录 1 网络1.1 局域网1.2 以太网1.3 城域网1.4 广域网1.5 互联网(因特网)1.6 万维网1.7 小结 2 IP 地址2.1 IP 地址2.2 端口号2.3 Mac 地址2.4 小结 3 客户端与服务端3.1 客户端3.2 服务端3.3 网络游戏中的客户端与服务端 1 网络 在没有网络之前…...
2025-03-17 学习记录--C/C++-PTA 习题4-8 高空坠球
合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻 一、题目描述 ⭐️ 习题4-8 高空坠球 皮球从某给定高度自由落下,触地后反弹到原高度的一半,再落下&…...
Java网络编程socket
一、UDP 特点: ① 用户数据报协议(User Datagram Protocol) ② UDP是面向无连接通信协议 ③ 速度快,一次只能传输64KB数据,数据不安全,容易丢失 (1)单播 一对一 客户端…...
蓝桥杯备赛 Day0_移动零
🎈 个人主页👉:tbRNA-CSDN博客tbRNA-CSDN博客tbRNA-CSDN博客 💯 个人简介:在校大学生一枚💋. 😍 希望我的文章对大家有着不一样的帮助,欢迎大家关注我,感谢大家的多多支持…...
Razor C# 变量
Razor C# 变量 引言 在ASP.NET MVC和Razor视图引擎中,变量是构建动态网页的基础。理解Razor C#变量的使用对于开发者来说至关重要。本文将详细介绍Razor C#变量的概念、类型、作用域以及如何在实际项目中有效使用它们。 一、Razor C# 变量的概念 Razor C# 变量是存储在Raz…...
产品更新丨谷云科技ETLCloud 3月更新速递
本月,我们的数据集成产品ETLCloud继续迎来多项更新,进一步提升系统的兼容性和用户体验。以下是本月更新的亮点内容: 新增10项功能组件,持续丰富产品易用性 聚水潭-奇门通用组件 新增聚水潭-奇门通用组件,帮助企业更…...
如何高效定位网络丢包问题?
引言 本期分享一个比较常见的网络问题--丢包。例如我们去ping一个网站,如果能ping通,且网站返回信息全面,则说明与网站服务器的通信是畅通的,如果ping不通,或者网站返回的信息不全等,则很可能是数据被丢包…...
gitlab将本地项目提交到远程dev分支
获取Git路径 首先从远程获取到git路径,将给的git地址进行克隆到本地文件; git clone http:************.git 按照git地址的文件路径将本地项目,拷贝到目标文件中 在该路径中,初始化命令; # 初始化项目 git init #…...
Linux命令学习使用列表
Linux命令学习使用列表 1 系统启动相关2 系统网络相关3 系统磁盘相关4 系统定时任务5 系统进程监控 1 系统启动相关 1.1 麒麟V10 sp3修改选择默认启动项 2 系统网络相关 2.1 Linux IP 配置 2.2 ping监测网络通信情况 3 系统磁盘相关 4 系统定时任务 5 系统进程监控 5.1 L…...
分布式锁: 并发时,redis如何避免删别人的锁
在使用Redis实现分布式锁的时候,如何避免在并发情况下误删别人的锁。首先,分布式锁的基本概念:是多个客户端在访问共享资源时,通过某种机制来确保同一时间只有一个客户端能持有锁。 Redis通常用SET命令加上NX选项来创建锁…...
解决 Jupyter Notebook 中本地模块修改不生效的问题
解决 Jupyter Notebook 中本地模块修改不生效的问题 问题原因 当你在 Jupyter Notebook 中导入本地目录的库,修改后重新运行 import 语句却发现修改没有生效,这是因为 Python 的模块缓存机制。Python 解释器会将已导入的模块缓存在 sys.modules 字典中…...
蓝桥杯嵌入式赛道复习笔记2(按键控制LED灯,双击按键,单击按键,长按按键)
硬件原理解释 这张图展示了一个简单的按键电路原理图,其中包含四个按键(PB0、PB1、PB2、PB3、PA0),每个按键通过一个10kΩ的上拉电阻连接到VDD(电源电压),并接地(GND)。 …...
简单爬虫--框架
简单爬虫 import requests import re import chardet# 模拟浏览器的请求头 headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" }# 发送 HTTP 请求获取百…...
游戏引擎学习第163天
我们可以在资源处理器中使用库 因为我们的资源处理器并不是游戏的一部分,所以它可以使用库。我说过我不介意让它使用库,而我提到这个的原因是,今天我们确实有一个选择——可以使用库。 生成字体位图的两种方式:求助于 Windows 或…...