Java并发编程之锁的艺术:面试与实战指南(三)
Java并发编程之锁的艺术:面试与实战指南(三)
文章目录
- Java并发编程之锁的艺术:面试与实战指南(三)
- 前言
- 十七、Java中线程和进程的区别是什么?
- 十八、什么是Java内存模型(JMM)?它在并发编程中有什么作用?
- 十九、volatile关键字的作用是什么?能保证线程安全吗?
- 二十、什么是线程局部变量(ThreadLocal)?它在什么场景下使用?
- 二十一、什么是阻塞队列?它在Java并发包中是如何实现的?
- ArrayBlockingQueue:
- LinkedBlockingQueue:
- PriorityBlockingQueue:
- DelayQueue:
- LinkedTransferQueue:
- 二十二、什么是Future和Callable?它们在并发编程中有什么应用?
- 二十三、什么是ForkJoinPool?它适用于哪些场景?
- 二十四、如何在Java中实现线程间的通信?
- 二十五、什么是CAS操作?它在Java并发中有什么应用?
- 二十六、Java中的原子类有哪些?它们是如何保证原子性的?
🌈你好呀!我是 山顶风景独好
💝欢迎来到我的博客,很高兴能够在这里和您见面!
💝希望您在这里可以感受到一份轻松愉快的氛围!
💝不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
🚀 欢迎一起踏上探险之旅,挖掘无限可能,共同成长!
前言
本系列地址:
Java并发编程之锁的艺术:面试与实战指南(一)
Java并发编程之锁的艺术:面试与实战指南(二)
Java并发编程之锁的艺术:面试与实战指南(三)
十七、Java中线程和进程的区别是什么?
- 定义与关系:进程是程序在处理机上的一次动态执行过程,而线程是进程的一个实体,是CPU调度和分派的基本单位。一个操作系统中可以拥有多个进程,一个进程里可以拥有多个线程,线程在进程内执行。
- 资源占用:进程拥有自己独立的内存空间和系统资源,而线程使用进程的内存空间,并和该进程的其他线程共享这个空间。
- 通信方式:线程可以使用wait(), notify(), notifyAll()等方法直接与其他线程(同一进程)通信;而进程需要使用“进程间通信”(IPC)来与操作系统中的其他进程通信。
- 创建与切换开销:由于进程拥有独立的资源,因此创建和销毁进程的开销通常比线程大。而线程是处理器任务调度和执行的基本单位,线程的创建、切换和销毁的开销相对较小。
- 独立性:进程是系统中独立存在的实体,是一个能独立运行的单位;而线程不拥有系统资源,只拥有一点在运行中必不可少的资源,但可以与同属一个进程的其他线程共享进程所拥有的全部资源。
十八、什么是Java内存模型(JMM)?它在并发编程中有什么作用?
Java内存模型(JMM)是Java虚拟机(JVM)规范中定义的一种内存模型,它描述了Java程序中各种变量(包括实例字段、静态字段和数组元素)的访问规则,以及在多线程环境中这些变量的可见性、原子性和有序性的保证。JMM并不真实存在,它仅仅是一组规则或规范,通过这组规范定义了程序中各个变量的读写访问方式。
在并发编程中,JMM的作用主要体现在以下几个方面:
- 屏蔽系统和硬件的差异:由于不同的硬件生产商和不同的操作系统下,内存的访问逻辑有一定的差异,JMM能够屏蔽这些差异,使得Java程序能够在不同的系统环境下达到相同的访问结果,实现“一次编写,到处运行”的目标。
- 保证多线程之间对共享变量操作的原子性、可见性和有序性:JMM通过定义如何通过synchronized和其他同步方式来保证这些特性。原子性指的是一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行;可见性指的是当一个线程修改了共享变量的值,其他线程能够立即得知这个修改;有序性指的是程序执行的顺序按照代码的先后顺序执行。
- 定义线程和主内存之间的抽象关系:JMM定义了JVM在计算机内存(RAM)中的工作方式,每个线程都有自己的独立工作内存,里面保存了该线程使用的变量的副本。线程对共享变量的所有操作都必须从自己的工作内存中读写,不能直接从主内存中读写。不同线程之间不能直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
十九、volatile关键字的作用是什么?能保证线程安全吗?
-
volatile关键字的主要作用是确保多线程环境下的变量可见性。当一个变量被声明为volatile时,它会保证修改的值会立即被更新到主内存,当有其他线程需要读取这个变量时,它会去主内存中读取新值。这样可以避免由于线程的工作内存和主内存中的数据不一致而导致的“脏读”问题。
-
此外,volatile关键字还可以禁止JVM的指令重排优化,这有助于保持程序执行的顺序性。
-
然而,需要注意的是,虽然volatile关键字可以保证可见性和禁止指令重排优化,但它并不能保证复合操作的原子性。也就是说,如果多个线程同时对同一个volatile变量进行复杂的读写操作(如自增、自减等),仍然可能出现线程安全问题。
二十、什么是线程局部变量(ThreadLocal)?它在什么场景下使用?
线程局部变量(ThreadLocal)是一种特殊的变量类型,它可以让多个线程并发访问时每个线程都有自己的变量副本,互不干扰。这种机制使得每个线程都可以独立地拥有和操作自己的变量副本,而不会影响到其他线程。
在Java中,可以使用ThreadLocal类来实现线程局部变量。ThreadLocal对象通常是一个静态成员变量,可以在多个线程间共享。每个线程通过ThreadLocal对象获取和设置自己独立的变量副本,不会与其他线程的变量产生冲突。每个线程都可以独立地修改自己的副本,而不需要加锁。
线程局部变量的应用场景:
- 线程安全的共享变量:在多线程环境中,如果我们想要在不同的线程间共享一些变量,但又不想让这些变量被多个线程修改,这个时候就可以使用ThreadLocal。例如,在一个网络应用中,我们可能需要在每个线程中维护一个与客户端的连接信息。使用ThreadLocal,我们可以在每个线程中创建一个连接信息的副本,这样每个线程都可以独立地操作自己的连接信息,而不会影响到其他线程。
- 线程专属的数据:有些时候,我们可能需要在每个线程中维护一些专属的数据,这些数据在其他线程中是不可见的。使用ThreadLocal,我们可以在每个线程中创建一个数据库连接的副本,这样每个线程都可以独立地操作自己的数据库连接,而不会影响到其他线程。
二十一、什么是阻塞队列?它在Java并发包中是如何实现的?
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加操作是:在队列为空时,获取元素的线程会等待队列变为非空;当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。
阻塞队列的实现依赖于Java的内置锁或显式Lock来实现线程间的同步,并使用了Condition来实现线程间的等待/通知机制。具体来说,当队列为空时,消费者线程会调用Condition的await()方法进入等待状态,直到生产者线程向队列中插入了元素并调用Condition的signal()或signalAll()方法唤醒等待的线程;当队列满时,生产者线程也会调用Condition的await()方法进入等待状态,直到消费者线程从队列中取出了元素并唤醒了等待的生产者线程。
JDK 8中阻塞队列的实现:
ArrayBlockingQueue:
- 这是一个基于数组实现的有界阻塞队列。队列按照先进先出(FIFO)的原则对元素进行排序。
LinkedBlockingQueue:
- 这是一个基于链表实现的有界阻塞队列。其默认和最大长度为Integer.MAX_VALUE,也就是说,它是一个几乎无界的队列。队列同样按照先进先出的原则进行排序。
PriorityBlockingQueue:
- 这是一个支持优先级排序的无界阻塞队列。默认情况下,元素按照自然排序(升序)进行排列。如果元素实现了Comparable接口,那么元素就会按照其compareTo()方法的返回值进行排序;如果元素没有实现Comparable接口,但在创建PriorityBlockingQueue时传入了Comparator对象,那么元素就会按照Comparator的compare()方法的返回值进行排序。
DelayQueue:
- 这是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现,队列中的元素必须实现Delayed接口。在创建元素时,可以指定多久才能从队列中获取当前元素,只有在延时期满时才能从队列中提取元素。队列头的元素是最先“到期”的元素。
LinkedTransferQueue:
- 这是一个由链表结构构成的无界阻塞TransferQueue队列。相对于其他阻塞队列,它多了tryTransfer和transfer方法。这个队列是LinkedBlockingQueue、SynchronousQueue(公平模式)和ConcurrentLinkedQueue三者的集合体,它综合了这三者的方法,并提供了更加高效的实现方式。
二十二、什么是Future和Callable?它们在并发编程中有什么应用?
- Callable:Callable是一个接口,它允许我们执行一个任务并返回结果。与Runnable接口不同,Runnable任务不返回任何结果,而Callable可以返回一个V类型的值。Callable的任务通常在线程池中执行,可以利用Future来获取任务的结果。Callable接口只包含一个call()方法,该方法可以抛出异常,这使得错误处理更加灵活。
- Future:Future是一个接口,用于获取异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。在并发编程中,我们通常将Callable任务提交给线程池执行,并通过Future对象来跟踪任务的状态和结果。
在并发编程中的应用
- 并行计算:使用Callable和Future可以方便地实现并行计算,将一个大任务拆分为多个小任务并在多个线程中并行执行。通过将计算任务分配给不同的线程,可以提高计算速度和系统的吞吐量。
- 异步IO:在网络编程和文件处理等场景中,使用Callable和Future可以实现异步IO操作。可以将IO操作封装为Callable任务,并通过Future对象获取IO操作的结果。这样可以充分利用CPU资源,同时不会阻塞主线程。
二十三、什么是ForkJoinPool?它适用于哪些场景?
ForkJoinPool是JDK7提供的一种基于“分治算法”的多线程并行计算框架。其核心思想是将大的任务拆分成多个小任务(即fork),然后再将多个小任务处理汇总到一个结果上(即join),非常像MapReduce处理原理。它特别适用于任务分解与合并的场景。
ForkJoinPool适用于那些可以自然分解为多个独立子任务,并且这些子任务之间不需要太多通信或同步的问题。
使用场景:
- 并行数组处理:如排序、过滤、映射等。
- 并行集合处理:如归约操作等。
- 科学计算中的并行算法:如矩阵乘法、快速傅里叶变换等。
相比于ThreadPoolExecutor,ForkJoinPool可以更好地实现计算的负载均衡,提高资源利用率。例如,当存在一个大任务和多个小任务时,ThreadPoolExecutor可能会导致一个线程忙于大任务,而其他线程则处于空闲状态。而ForkJoinPool则可以将大任务拆分成多个小任务,然后这些小任务被所有的线程执行,从而实现任务计算的负载均衡。
此外,ForkJoinPool还引入了“工作窃取”机制,在多CPU计算机上处理性能更佳。当一个线程完成了自己的任务后,它可以从其他线程的工作队列中“窃取”一个任务来执行,从而充分利用系统资源。
二十四、如何在Java中实现线程间的通信?
-
共享变量:
线程之间可以通过共享变量进行通信。但是,必须确保对共享变量的访问是同步的,以防止并发修改导致的数据不一致。可以使用synchronized关键字、Lock接口或Atomic类来确保同步。 -
wait/notify/notifyAll:
Object类提供了wait(), notify(), 和 notifyAll() 方法,这些方法可以用于在线程之间通信。一个线程可以调用共享对象的wait()方法进入等待状态,直到其他线程调用该对象的notify()或notifyAll()方法将其唤醒。这种方法通常与synchronized一起使用,以确保线程安全。 -
BlockingQueue:
Java并发包(java.util.concurrent)中的BlockingQueue接口为线程间的通信提供了一种安全高效的方式。BlockingQueue实现类(如ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue等)提供了put(), take(), offer(), poll()等方法用于在队列中添加和移除元素。这些方法在队列为空或满时会阻塞线程,从而实现线程间的通信。 -
Semaphore:
Semaphore是一个基于计数的信号量,可以用来控制对多个共享资源的访问。它也可以用于实现线程间的通信。通过减少信号量的值(acquire()方法)来阻塞线程,通过增加信号量的值(release()方法)来唤醒线程。 -
CyclicBarrier:
CyclicBarrier是一个可以让一组线程互相等待,直到所有线程都到达某个公共屏障点的同步工具。在屏障点处,线程可以选择继续执行或执行一些特殊操作,从而实现线程间的通信。 -
CountDownLatch:
CountDownLatch是一个同步辅助类,允许一个或多个线程等待一组其他线程完成操作。当调用countDown()方法时,计数器会减一;当计数器到达零时,等待的线程将被唤醒,从而实现线程间的通信。 -
Exchanger:
Exchanger是一个用于两个线程之间交换数据的同步点。两个线程通过exchange()方法交换数据,如果其中一个线程先到达交换点,它会一直等待另一个线程到达才进行交换,从而实现线程间的通信。 -
Future和Callable:
虽然Future和Callable本身不直接用于线程间通信,但它们可以用于获取异步计算的结果。通过Future的get()方法,一个线程可以等待另一个线程完成计算并获取结果,从而实现间接的线程间通信。
二十五、什么是CAS操作?它在Java并发中有什么应用?
CAS(Compare-And-Swap)操作是一种无锁操作,它通过比较内存中的值与预期值是否相等来实现原子操作,解决并发环境下的数据竞争问题。
- CAS操作包含三个值:V(内存地址存放的实际值)、O(预期的值,即旧值)和N(更新的新值)。
- 它的工作原理是,当线程需要使用某个共享变量时,会先将其值(V)与预期值(O)进行比较,如果两者相等,则说明该值没有被其他线程修改过,线程可以将该值更新为新值(N)。这个过程是原子的,即不会被其他线程打断。
在Java中,CAS操作通常通过sun.misc.Unsafe类实现,该类提供了硬件级别的原子操作。由于CAS操作不需要加锁,因此它可以避免加锁操作所带来的性能开销,提高程序的并发性能。
CAS应用场景:
- 原子性操作:CAS操作可以用于实现原子性操作,如计数器的自增、自减等。由于CAS是一种无锁操作,因此它可以避免使用锁机制所带来的开销,使得原子性操作更加高效。
- 并发控制:CAS操作可以用于实现乐观锁机制,通过不断尝试更新共享变量的值来实现并发控制。如果更新失败(即预期值与内存中的值不相等),则说明有其他线程正在修改该值,当前线程可以选择重试或放弃操作。
- 无锁数据结构:CAS操作可以用于实现无锁数据结构,如无锁队列、无锁链表等。这些数据结构通过CAS操作来确保线程安全,避免了使用锁机制所带来的开销和死锁问题。
需要注意的是,虽然CAS操作具有高效性和无阻塞性等优点,但它也存在一些问题和限制。例如,CAS操作只能保证单个共享变量的原子性操作,对于多个共享变量的复合操作则无法保证原子性。此外,CAS操作还存在ABA问题(即一个值被其他线程修改后又改回原来的值,但当前线程并不知道这个变化过程),这可能会导致程序出现错误。
二十六、Java中的原子类有哪些?它们是如何保证原子性的?
Java中的原子类(Atomic Classes)主要用于在高并发的情况下,实现线程安全的操作。这些原子类位于java.util.concurrent.atomic包中,包括AtomicInteger、AtomicLong、AtomicBoolean等基本类型的原子类,以及AtomicReference引用类型的原子类。此外,还有AtomicIntegerFieldUpdater、AtomicLongFieldUpdater等原子更新器类,用于对某个类的字段进行原子更新。
-
原子类保证原子性的主要方式是通过底层使用CAS(Compare-And-Swap)机制。CAS是一种基于硬件支持的原子操作,它包含三个参数:内存地址V、预期的原值A和新值B。当且仅当内存地址V的值等于预期的原值A时,才会将V的值更新为新值B。如果V的值与A不相等,说明已经有其他线程修改了V的值,此时当前线程可以选择重新读取V的值并再次尝试更新,或者选择放弃更新。这种机制可以确保在并发环境下对共享变量的更新是原子性的。
-
与synchronized关键字和Lock锁相比,原子类在粒度上更细,可以把竞争范围缩小到变量级别,从而获得更细粒度的并发控制。此外,原子类通常比使用锁的效率更高,除了在高度竞争的情况下。这是因为CAS操作是一种无锁操作,它避免了加锁和解锁的开销,减少了线程间的竞争和阻塞。
-
需要注意的是,虽然原子类提供了线程安全的操作,但在使用时仍需要注意避免ABA问题(即一个值被其他线程修改后又改回原来的值,但当前线程并不知道这个变化过程)和循环时间长开销大等问题。此外,对于多个共享变量的复合操作,仍需要使用锁或其他同步机制来确保原子性。
相关文章:
Java并发编程之锁的艺术:面试与实战指南(三)
Java并发编程之锁的艺术:面试与实战指南(三) 文章目录 Java并发编程之锁的艺术:面试与实战指南(三)前言十七、Java中线程和进程的区别是什么?十八、什么是Java内存模型(JMMÿ…...
Final Draft 12 for Mac:高效专业剧本创作软件
对于剧本创作者来说,一款高效、专业的写作工具是不可或缺的。Final Draft 12 for Mac就是这样一款完美的选择。这款专为Mac用户设计的剧本创作软件,凭借其卓越的性能和丰富的功能,让您的剧本创作更加得心应手。 Final Draft 12支持多种剧本格…...
php字符串变量和常见的字符串函数
在 PHP 中,字符串变量用于存储文本数据。你可以使用单引号()、双引号(")或定界符(heredoc 或 nowdoc)来定义字符串。下面是一些关于 PHP 字符串变量的重要点和示例: 1. 单引号…...
PPT基础
5种ppt仅可读形式 Ⅰ 开始选项卡 1.【幻灯片】组中:新建幻灯片,从大纲中导入幻灯片;修改幻灯片的版式;节(新增节,重命名节)。 2.【字体】组中:设置字体,字体大小&…...
初识JDBC
1、JDBC是什么? Java DataBase Connectivity(Java语言连接数据库) 2、JDBC的本质是什么? JDBC是SUN公司制定的一套接口(interface) java.sql.*;(这个包下有很多接口) 接口都有调用者和实现者。 面向接口调用、面向接口写实现类,这都属于…...
React 学习-5
React 条件渲染: 与js中的写法一致 注意:在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。 因此,如果条件是 true,&& 右侧的元素就会被渲…...
深入浅出TCP 与 UDP
🔥 个人主页:空白诗 文章目录 🔥 引言🌐 基础认知概览💻 TCP - 稳健的信使 🛡️🎭 UDP - 敏捷的使者 🏃♂️ 🧑💻 实战演练:代码示例TCP 服务…...
Leetcode—387. 字符串中的第一个唯一字符【简单】
2024每日刷题(127) Leetcode—387. 字符串中的第一个唯一字符 实现代码 class Solution { public:int firstUniqChar(string s) {int count[26] {0};for(char c: s) {count[c - a];}for(int i 0; i < s.length(); i) {if(count[s[i] - a] 1) {re…...
Blazor入门-调用js+例子
参考: Blazor入门笔记(3)-C#与JS交互 - 半野 - 博客园 https://www.cnblogs.com/zxyao/p/12638233.html 本地环境:win10, visual studio 2022 community 其他例子写了再更新! 调用js函数并传递参数 首先要加上injec…...
暴力数据结构之栈与队列(队列详解)
1.队列的定义 队列是一种特殊的线性表,它遵循先进先出(FIFO)的原则。在队列中,只允许在表的一端进行插入操作(队尾),而在另一端进行删除操作(队头)。这种数据结构确保了最…...
仿照JDK源码写一个ArrayList实现
仿照JDK编写一个简化的ArrayList实现是一个很好的学习Java集合框架内部工作原理的方式。以下是一个简化版的ArrayList实现,它包含了基本的添加、获取、删除和大小检查功能。 public class MyArrayList<E> {private static final int DEFAULT_CAPACITY = 10;private Obj…...
[链表专题]力扣21, 234
1. 力扣21 题 : 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1:输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4] 示例 2:输入:l1 [], l2 [] 输出&…...
智慧便民小程序源码系统 求职招聘+房产出租+相亲交友 带完整的安装代码包以及系统搭建教程
在数字化、智能化的今天,我们的生活节奏越来越快,对于各种服务的需求也越发多元化和个性化。为了满足广大市民对于便捷、高效、全面的服务需求,罗峰给大家分享一款智慧便民小程序源码系统,集求职招聘、房产出租、相亲交友三大功能…...
苹果免签封装的优势和安全风险
哈喽,大家好呀,淼淼又来和大家见面啦,许多小伙伴应该都知道,App Store一直是iOS应用的主要分发渠道,苹果生态系统的监管是十分严格的,以此确保了应用质量与用户的安全。而苹果免签封装则是有一种不需要通过…...
hook抓包trace定位实战
title: SO逆向之大众点评cx date: 2022-02-07 19:27:28 tags: SOfrida categories: 安卓逆向 toc_number: true抓包10.37.13 打开首页一篇文章,APP默认TCP连接,通过降级采用HTTP连接 jadx反编译代码中 public int g() {Object[] objArr = new Object[0];ChangeQuickRedire…...
SMB 协议详解之-TreeID原理和SMB数据包分析技巧
在前面分析SMB协议数据包的过程中,这里,可以看到在SMB协议中存在很多的ID,即Unique Identifiers。那么这些ID表示什么含义?在实际分析数据包的过程中如何根据这些ID进行过滤分析?本文将介绍SMB/SMB2中的tree id ,并介绍如何通过tree id 快速的分析SMB数据包中各种命令交互…...
博士阶段应该搞什么:-人才引进要求
目录 专利,高水平论文(一作),技能证书,职称,高端竞赛,科研成果奖 济宁学院...
超全MySQL锁机制介绍
前言 MySQL作为关系型数据库管理系统中的佼佼者,为了保证数据的一致性和完整性,在并发控制方面采用了锁机制。锁机制是数据库管理系统用于控制对共享资源的访问,避免多个事务同时修改同一数据造成的数据不一致问题。了解MySQL的锁机制对于数…...
【CV】计算机视觉中的特征追踪与背景处理
计算机视觉领域中的重要任务之一是视频特征追踪,它可以用于目标跟踪、运动分析、行为识别等应用。然而,在实际应用中,经常会遇到需要仅处理视频中特定特征物体而忽略背景的情况,这就需要进行背景处理。本文将介绍如何使用Python和…...
CAPL如何实现TLS握手认证
CAPL有专门的章节介绍如何实现TLS握手认证的函数: CAPL调用哪些函数实现TLS握手认证,需要了解TLS在整个通信过程的哪个阶段。 首先TCP需要建立连接,这是TLS握手的前提。当TLS握手认证完成后,可以传输数据。 所以TLS握手开始前需要确保TCP建立连接,TCP传输数据前需要确保…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
