java面试(多线程)

线程和进程的区别

程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存。在指令运行过程中还需要用到磁盘,网络等设备。进程就是用来加载指令,管理内存,管理IO的。
当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。
一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行
一个进程之内可以分为一到多个线程
二者对比:

  1. 进程是正在运行程序的实例,进程中包含了线程,每个线程执行不同的任务
  2. 不同的进程使用不同的内存空间,在当前进程下的所有线程可以共享内存空间
  3. 线程更轻量,线程上下文切换成本一般上要比进程上下文切换低(上下文切换指的是从一个线程切换到另一个线程)

并行和并发的区别

单核CPU

  1. 单核CPU下线程实际还是串行执行的
  2. 操作系统中有一个组件叫做任务调度器,将cpu的时间片(windows下时间片最小约为15ms)分给不同的程序使用,只是由于cpu在线程间(时间片很短)的切换非常快,人类感觉是同时运行的
  3. 总结为一句话就是:微观串行,宏观并行
  4. 一般会将这种线程轮流使用CPU的做法叫做并发(concurrent)

多核CPU

每个核(core)都可以调度运行线程,这时候线程可以是并行的
对比
并发(concurrent)是同一时间应对(dealing with)多件事情的能力
并行(parallel)是同一时间动手做(doing)多件事情的能力
在这里插入图片描述

创建线程的方式

共有四种方式可以创建线程,分别是:

  1. 继承Thread类
  2. 实现runnable接口
  3. 实现callable接口
  4. 线程池创建线程

继承Thread类

在这里插入图片描述

实现runnable接口

在这里插入图片描述

实现Callable接口

在这里插入图片描述

线程池创建线程

在这里插入图片描述

使用runnable和callable创建线程的区别

  1. Runnable接口run方法没有返回值
  2. callable接口call方法有个返回值,是个泛型,和Future,FutureTask配合可以用来获取异步执行的效果
  3. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛

线程的run()和srart()有什么区别

start()用来启动线程,通过该线程调用run方法执行run方法中定义的逻辑代码。start方法只能被调用一次。
run()封装了要被线程执行的代码,可以被调用多次

线程包括哪些状态,状态之间是如何变化的

线程的状态可以参考JDK中Thread类中的枚举State

在这里插入图片描述
在这里插入图片描述

线程包括哪些状态

  1. 新建(NEW)
  2. 可运行(RUNNABLE)
  3. 阻塞(BLOCKED)
  4. 等待(WAITING)
  5. 时间等待(TIMED_WAITING)
  6. 终止(TREMINATED)

线程之间的状态是如何变化的

  1. 创建线程对象是新建状态
  2. 调用了start()方法转变为可执行状态
  3. 线程获取到了CPU的执行权,执行结束是终止状态
  4. 在可执行状态的过程中,如果没有获取CPU的执行权,可能会切换其他状态
    1. 如果没有获取锁(synchronized或lock)进入阻塞状态,获得锁再切换为可执行状态
    2. 如果线程调用了wait()方法进入等待状态,其他线程调用notify()唤醒后可切换为可执行状态
    3. 如果线程调用了sleep()方法,进入计时等待状态,到时间后可切换为可执行状态

新建T1,T2,T3三个线程,如何保证他们按顺序执行

可以使用线程中的join方法解决

notify和notifyAll有什么区别

  1. notifyAll:唤醒所有wait的线程
  2. notify:只随机唤醒一个wait线程

wait和sleep方法的不同

  1. 共同点:
    1. wait,wait(long),sleep(long)的效果都是让当前线程放弃CPU的使用权,进入阻塞状态
  2. 不同点:
    1. 方法归属不同
      1. sleep(long)是Thread的静态方法
      2. 而wait,wait(long)都是Object的成员方法,每个对象都有
    2. 醒来时机不同
      1. 执行sleep(long)和wait(long)的线程都会在等待相应毫秒后醒来
      2. wait(long)和wait()还可以被notify唤醒,wait()如果不唤醒就一直等下去
      3. 他们都可以被打断唤醒
    3. 锁特性不同(重点)
      1. wait方法的调用必须先获取wait对象的锁,而sleep则无限制
      2. wait方法执行后会释放对象锁,允许其他线程获得该对象锁(我放弃cpu,但你们还可以用)
      3. 而sleep如果在synchronized代码块中执行,并不会释放对象锁(我放弃cpu,你们也用不了)

如何停止一个正在运行的线程

有三种方式可以停止线程:

  1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止
  2. 使用stop方法强行终止(不推荐,方法已作废)
  3. 使用interrupt方法中断线程
    1. 打断阻塞的线程(sleep,wait,join)的线程,线程会抛出InterruptedException异常
    2. 打断正常的线程,可以根据打断标记来标记是否退出线程

synchronized关键字的底层原理

synchronized【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其他线程再想获取这个【对象锁】时就会阻塞住

Monitor

Monitor被翻译为监视器,是由jvm提供,c++语言实现
在这里插入图片描述

  1. Owner:存储当前获取锁的线程的,只有一个线程可以获取
  2. EntryList:关联没有抢到锁的线程,处于Blocked状态的线程
  3. WaitSet:关联调用了wait方法的线程,处于Waiting状态的线程

Monitor实现的锁属于重量级锁,你了解过锁升级吗

  1. Monitor实现的锁属于重量级锁,里面涉及到了用户态和内核态的切换,进程的上下文切换,成本较高,性能比较低
  2. 在JDK1.6引入了两种新型锁机制:偏向锁和轻量级锁,他们的引入是为了解决在没有多线程竞争或基本没有竞争的场景下使用传统锁机制带来的性能开销问题

对象的内存结构

在HotSpot虚拟机中,对象在内存中存储的布局可分为三块区域:对象头(Header),实例数据(Instance Data)和对齐填充
在这里插入图片描述

MarkWord

在这里插入图片描述

  1. hashcode:25位的对象表示Hahs码
  2. age:对象分代年龄占4位
  3. biased_lock:偏向锁标识,占1位,0表示没有开始偏向锁,1表示开启了偏向锁
  4. thread:持有偏向锁的线程ID,占23位
  5. epoch:偏向时间戳,占2位
  6. ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针,占30位
  7. prt_to_heavtweight_monitor:重量级锁状态下,指向对象Monitor的指针,占30位

重量级锁的对象是怎么关联上Monitor的呢

每个Java对象都可以关联一个Monitor对象,如果使用synchronized给对象上锁(重量级)之后,该对象的MarkWord中就被设置指向Monitor对象的指针

轻量级锁

在很多的情况下,在Java程序运行时,同步块中的代码都是不存在竞争的,不同的线程交替的执行同步块中的代码。这种情况下,用重量级锁hi没必要的。因此JVM引入了轻量级锁的概念
加锁流程:
1. 在线程栈中创建一个Lock Record,将其obj字段指向锁对象
2. 通过CAS指令将Lock Record的地址存储在对象头的mark word中,如果对象处于无锁状态则修改成功,代表该线程获得了轻量级锁
3. 如果是当前线程已经持有该锁了,代表这是一次锁重入。设置Lock Record第一部分为null,起到了一个重入计数器的作用
4. 如果CAS修改失败,说明发生了竞争,需要膨胀为重量级锁
解锁过程:
1. 遍历线程栈,找到所有obj字段等于当前锁对象的Lock Record
2. 如果Lock Record的Markword为null,代表这是一次重入,将obj设置为null后continue
3. 如果Lock Record的MarkWord不为null,则利用CAS指令将对象头的markword恢复成无锁状态。如果失败则膨胀为重量级锁。

偏向锁

轻量级锁在没有竞争的时候,每次重入仍然需要执行CAS操作
引入偏向锁来做进一步优化:只有第一次使用CAS将线程ID设置到对象的MarkWord头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS,以后只要不发生竞争,这个对象就归该线程所有。
在这里插入图片描述

JMM

  1. JMM(Java Memory Model)Java内存模型,定义了共享内存中多线程程序读写操作的行为规范,通过这些规则来规范对内存读写操作从而保证指令的正确性
  2. JMM把内存分为两块,一块是私有线程的工作区域(工作内存),一块是所有线程的共享区域(主内存)
  3. 线程跟线程之间是相互隔离,线程跟线程之间的交互需要通过主内存

在这里插入图片描述

CAS

CAS的全称是:Compare And Swap(比较再交换),他体现的是一种乐观锁的思想,在无锁情况下保证线程操作共享数据的原子性
在JUC(java.util.concurrent)包下实现的很多类都用到了CAS操作

  1. AbstractQueuedSynchornizer(AQS框架)
  2. AtomicXXX类

CAS数据交换流程

在这里插入图片描述
一个当前内存值V,旧的预期值A,即将更新的值B,当且仅当旧的预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false。如果CAS操作失败,通过自选的方式等待并再次尝试,直到成功。
在这里插入图片描述

  1. 因为没有加锁,所以线程不会陷入阻塞,效率较高
  2. 如果竞争激烈,重试频繁发生,效率会受影响

CAS底层实现

CAS底层依赖一个Unsafe类来直接调用操作系统底层的CAS指令

乐观锁和悲观锁

  1. CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算失败了也没关系
  2. synchronized是基于悲观锁的思想:最悲观的估计,得放着其他线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。

volatile

一旦一个共享变量(类的成员变量,类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

  1. 保证线程间的可见性
  2. 禁止进行指令重排序

保证线程间的可见性

用volatile修饰共享变量,能够防止编译器等优化发生,让一个线程对共享变量的修改对另一个线程可见。

禁止进行指令重排序

用volatile修饰共享变量会在读,写共享变量时加入不同的屏障,阻止其他读写操作越过屏障,从而达到阻止指令重排序的效果。
在这里插入图片描述
volatile使用技巧

  1. 写变量让volatile修饰的变量在代码的最后位置
  2. 读变量让volatile修饰的变量在代码的最开始位置

什么是AQS

全称是AbstractQueuedSynchronizer,即抽象队列同步器。他是构建锁或者其他同步组件的基础框架

AQS和synchronized的区别

synchronizedAQS
关键字,C++实现java语言实现
悲观锁,自动释放锁悲观锁,手动开启和关闭
锁竞争激烈都是重量级锁,性能差锁竞争激烈的情况下,提供了多种解决方案

AQS的常见类

  1. ReentrantLock:阻塞式锁
  2. Semaphore:信号量
  3. CountDownLatch:倒计时锁

AQS-基本工作机制

在这里插入图片描述

AQS多个线程共同争抢资源是如何保证原子性的

使用CAS设置state状态,保证操作的原子性

AQS是公平锁还是非公平锁

  1. 新的线程与队列中的线程共同来抢资源,是非公平锁
  2. 新的线程到队列中等待,只让队列中的head线程获得锁,是公平锁

ReentrantLock

ReentrantLock翻译过来是可重入锁,相对于synchronized他具备以下特点:

  1. 可中断
  2. 可以设置超时时间
  3. 可以设置公平锁
  4. 支持多个条件变量
  5. 与synchronized一样,都支持重入

实现原理

ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似
构造方法接受一个可选的公平参数(默认非公平锁),当设置为true时,表示公平锁,否则为非公平锁。公平锁的效率往往没有非公平锁高,在许多线程访问的情况下,公平锁表现出较低的吞吐量。
在这里插入图片描述

  1. 线程来抢锁后使用cas的方式修改state状态,修改状态成功为1,则让exclusiveOwnerThread属性指向当前线程,获取锁成功
  2. 假如修改状态失败,则会进入双向队列中等待,head指向双向队列头部,tail只想双向队列尾部
  3. 当exclusiveOwnerThread为null的时候,则会唤醒在双向队列中等待的线程
  4. 公平锁则体现在按照先后顺序获取锁,非公平体现在不在排队的线程也可以抢锁

synchronized和Lock有什么区别

  1. 语法层面
    1. synchronized是关键字,源码在jvm中,用c++实现
    2. Lock是接口,源码由jdk提供,用java语言实现
    3. 使用synchronized时,退出同步代码块锁会自动释放,而使用lock时,需要手动调用unlock方法释放锁
  2. 功能层面
    1. 两者均属于悲观锁,都具备基本的互斥,同步,锁重入功能
    2. Lock提供了许多synchronized不具备的功能,例如公平锁,可打断,可超时,多条件变量
    3. Lock有适合不同场景的实现,如ReentrantLock,ReentrantReadWriteLock(读写锁)
  3. 性能层面
    1. 在没有竞争时,synchronized做了很多优化,如偏向锁,轻量级锁,性能不赖
    2. 在竞争激烈时,Lock的实现通常会提供更好的性能

死锁产生的条件

死锁:一个线程需要同时获取多把锁,这时就容易发生死锁
线程t1持有A的锁等待获取B锁,线程t2持有B的锁等待获取A的锁

如何进行死锁诊断

当程序出现了死锁现象,我们可以使用jdk自带的工具:jps和jstack

  1. jps:输出JVM中运行的进程状态信息
  2. stack:查看java进程内线程的堆栈信息

其他解决工具

  1. jconsole:用于对jvm的内存,线程,类的监控,是一个基于jmx的GUI性能监控工具
  2. VisualVM:故障处理工具,能够监控线程,内存情况,查看方法的CPU时间和内存中的对象,已被GC的对象,反向查看分配的堆栈。

ConcurrentHashMap

ConcurrentHashMap是一种线程安全的高效Map集合,使用数组+链表/红黑二叉树实现
采用CAS+synchronized来保证并发安全进行实现

  1. CAS控制数组节点的添加
  2. synchronized只锁定当前链表或红黑二叉树的首节点,只要hash不冲突,就不会产生并发的问题,效率得到提升

导致并发程序出现问题的根本原因是什么

java并发编程中有三大特征

  1. 原子性:一个线程在CPU中操作不可暂停,也不可中断,要不执行完成,要不不执行
  2. 可见性:
  3. 有序性

内存可见性:让一个线程对共享变量的修改对另一个线程可见
有序性:指令重排:处理器为了提高程序运行效率,可能会对输入代码进行优化,他不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是他会保证程序最终执行结果和代码顺序的结果是一致的。

线程池的核心参数

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
  1. corePoolSize:核心线程数目
  2. maximumPoolSize:最大线程数目 = (核心线程 + 救急线程的最大数目)
  3. keepAliveTime生存时间-救急线程的生存时间,生存时间内没有新任务,此线程资源会释放
  4. unit:时间单位-救急线程的生存时间单位,如秒,毫秒等
  5. workQueue:当没有空闲和核心线程时,新的任务会加入到此队列排队,队列满会创建救急线程执行任务
  6. threadFactory:线程工厂-可以定制线程对象的创建,例如设置线程名字,是否是守护线程等

线程池的执行原理

在这里插入图片描述

线程池中有哪些常见的阻塞队列

workQueue-当没有空闲核心线程时,新来任务会假如到此队列排队,队列满会创建救急线程执行任务

  1. ArrayBlockingQueue:基于数组结构的有界阻塞队列,FIFO
  2. LinkedBlockingQueue:基于链表结构的有界阻塞队列,FIFO
  3. DelayedWrokQueue:是一个优先级队列,他可以保证每次出队的任务是当前队列中执行时间最靠前的
  4. SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移除操作
ArrayBlockingQueueLinkedBlockingQueue
默认无界,支持有界强制有界
底层是链表底层是数组
是懒惰的,创建节点的时候自动添加数据提前初始化Node数组
入队会生成新的NodeNode需要是提前创建好的
两把锁(头尾)一把锁

如何确定核心线程数

  1. IO密集型任务:一般来说:文件读写,DB读写,网络请求等=》核心线程数大小设置为2N+1
  2. CPU密集型任务:一般来说:计算型代码,Bitmap转换,Gson转换等:核心线程数大小设置为N+1

线程池的种类有哪些

在java.util.concurrent.Executors类中提供了大量创建连接池的静态方法,常见就有四种

  1. 创建使用固定线程数的线程池
    在这里插入图片描述
    1. 核心线程数与最大线程数一样,没有救急线程
    2. 阻塞队列是LinkedBlockingQueue,最大容量为Integer.MAX_VALUE
      适用于任务量已知,相对耗时的任务
  2. 单线程化的线程池,他只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO)执行
    在这里插入图片描述
    1. 核心线程数和最大线程数都是1
    2. 阻塞队列是LinkedBlockingQueue,最大容量为Integer.MAX_VALUE
      适用于按照顺序执行的任务
  3. 可缓存的线程池
    在这里插入图片描述
    1. 核心线程数为0
    2. 最大线程数为Integer.MAX_VALUE
    3. 阻塞队列为SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移除操作
      适合任务数比较密集,但每个任务执行时间较短的情况
  4. 提供了延迟和周期执行功能的ThreadPoolExectutor在这里插入图片描述

线程池的使用场景

CountDownLatch

CountDownLatch(闭锁/倒计时锁)用来进行线程同步协作,等待所有线程完成倒计时(一个或多个线程,等待其他多个线程完成某件事情后才能执行)

  1. 其中构造参数用来初始化等待计数值
  2. await()用来等待技术归零
  3. countDown()用来让计数减一

多线程使用场景(es数据批量导入)

在项目上线之前需要将数据库的数据批量导入到es索引库中,数据量高达一千万,一次性读取数据肯定会导致OOM,于是可以使用线程池方式导入,利用countDownLatch来控制,避免一次性加载太多,防止内存溢出

如何控制某个方法允许并发访问线程的数量

Semaphore信号量,是JUC包下的一个工具类,底层是AQS,我们可以通过其限制执行的线程数量
使用场景:通常用于那些资源有明确访问数量限制的场景,常用于限流

Semaphore使用步骤

  1. 创建Semaphore对象,可以给一个容量
  2. semaphore。acquire():请求一个信号量,这时候的信号量个数-1(一旦没有可使用的信号量,也即信号量个数变为负数时,再次请求的时候就会阻塞,知道其他线程释放了信号量)
  3. semaphore.release():释放一个信号量,此时信号量个数+1

对ThreadLocal的理解

ThreadLocal是多线程中对于解决线程安全的一个操作类,他会为诶个线程都分配一个独立的线程副本从而解决了变量并发访问冲突的问题。ThreadLocal同时实现了线程内的资源共享

ThreadLocal的基本使用

  1. set(value)设置值
  2. get():获取值
  3. remove()清除值

ThreadLocal的实现原理&源码解析

ThreadLocal本质来说就是一个线程内部存储类,从而让多个线程只操作自己内部的值,从而实现线程数据隔离

ThreadLocal内存泄漏问题

Java对象中的四种引用类型:强引用,软引用,弱引用,虚引用

  1. 强引用:最为普通的引用方式,表示一个对象处于有用且必须得状态,如果一个对象具有强引用,则GC并不会回收它。即是堆内存不足了,宁可出现OOM,也不会对其进行回收。
  2. 弱引用:表示一个对象处于可能有用且必须得状态。在GC线程扫描内存区域时,一旦发现弱引用,就会回收到弱引用相关联的对象。对于弱引用的回收,无关内存区域是否足够,一旦发现则会被回收。
    每一个Thread维护一个ThreadLocalMap,在ThreadLocalMap中的Entry对象继承了WeakReference。其中key为使用弱引用的ThreadLocal实例,value为线程变量的副本
    防止内存泄漏:必须remove

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

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

相关文章

Android11热点启动和关闭

Android官方关于Wi-Fi Hotspot (Soft AP) 的文章&#xff1a;https://source.android.com/docs/core/connect/wifi-softap?hlzh-cn 在 Android 11 的WifiManager类中有一套系统 API 可以控制热点的开和关&#xff0c;代码如下&#xff1a; 开启热点&#xff1a; val builde…

基于IP子网vlan划分

在某些场景中&#xff0c;客户的终端地址都是固定的&#xff0c;并且有移动的需求&#xff0c;也就是接口不固定&#xff0c;这时候基于接口的VLAN就不合适了&#xff0c;因为通常情况下一个VLAN属于一个网段&#xff0c;对于这种接口之间任意插还能保证业务不受影响的&#xf…

记录centos中操作(查找、结束、批量)进程以及crontab定时写法的知识

环境&#xff1a;vps&#xff0c;centos7&#xff0c;python3。 近期写了个python程序&#xff0c;用青龙面板在centos上运行。程序中有while无限循环&#xff0c;但是我在青龙中设置了定时任务&#xff08;每隔半小时运行一次&#xff09;&#xff0c;于是造成了进程中有多个…

分布式文件系统minIo

分布式文件系统 什么是分布式文件系统 一个计算机无法存储海量的文件&#xff0c;通过网络将若干计算机组织起来共同去存储海量的文件&#xff0c;去接收海量用户的请求&#xff0c;这些组织起来的计算机通过网络进行通信&#xff0c;如下图&#xff1a; 好处&#xff1a; 1、…

Wpf 使用 Prism 实战开发Day22

客户端添加IDialogService 弹窗服务 在首页点击添加备忘录或待办事项按钮的时候&#xff0c;希望有一个弹窗&#xff0c;进行相对应的内容添加操作。 一.在Views文件夹中&#xff0c;再创建一个Dialog 文件夹&#xff0c;用于放置备忘录和待办事项的弹窗界面。 1.1 备忘录&…

js实现鼠标拖拽多选功能

实现功能 在PC端的H5页面中&#xff0c;客户拖动鼠标可以连选多个选项 效果展示 具体代码如下 <!DOCTYPE html> <html><head><title>鼠标拖拽多选功能</title><script src"https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js&quo…

ZISUOJ 数据结构--图及其应用

说明 主要考察建图&#xff0c;图的遍历以及求最小生成树。都还是比较简单的&#xff0c;后面就直接上代码了。 最小生成树采用prim还是kruskal算法要看题目怎么给出数据&#xff0c;如果以邻接矩阵的形式给出&#xff0c;采用prim算法比较合适&#xff0c;如果以边和边的权重的…

docker三种自定义网络(虚拟网络) overlay实现原理

docker提供了三种自定义网络驱动&#xff1a;bridge、overlay、macvlan。 bridge驱动类似默认的bridge网络模式。 overlay和macvlan是用于创建跨主机网络。 支持自定义网段、网关&#xff0c;docker network create --subnet 172.77.0.0/24 --gateway 172.77.0.1 my_n…

浅谈JMeter测试计划

浅谈JMeter测试计划 创建测试计划 当启动JMeter后&#xff0c;默认进入界面会看到一个测试计划 测试计划组件详情 在上述界面中&#xff0c;我们可以看到测试计划的组成为名称、注释、用户定义的变量、独立运行每个线程组、主线程结束后运行tearDown线程组、函数测试模式以…

科技查新中查新点的怎样进行精确提炼?

根据2015年《科技查新技术规范》&#xff1a;科技查新简称查新&#xff0c;以反映查新项目主题内容的查新点为依据&#xff0c;以计算机检索为主要手段&#xff0c;以获取密切相关文献为检索目标&#xff0c;运用综合分析和对比方法&#xff0c;对查新项目的新颖性做出文献评价…

JMETER工具:以录制手机app为例

JMETER工具&#xff1a;以录制手机app为例子 JMETER安装和环境配置 pc需要安装jdk&#xff0c;并进行jdk的环境配置&#xff0c;安装好jdk并配置好后&#xff0c;通过命令行输入java –version出现以下界面就表示安装成功&#xff1a; &#xff08;对应的jdk版本不可太低&…

深度学习——图像分类(CNN)—训练模型

训练模型 1.导入必要的库2.定义超参数3.读取训练和测试标签CSV文件4.确保标签是字符串类型5.显示两个数据框的前几行以了解它们的结构6.定义图像处理参数7.创建图像数据生成器8.设置目录路径9.创建训练和验证数据生成器10.构建模型11.编译模型12.训练模型并收集历史13.绘制损失…

excel转pdf并且加水印,利用ByteArrayOutputStream内存流不产生中间文件

首先先引入包&#xff1a;加水印和excel转PDF的 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.12</version></dependency><dependency><groupId>org.apache.poi&l…

jenkins插件之xunit

安装jenkins插件 搜索xunit并安装 项目配置 配置 - Build Steps 您的项目 - 配置 - Build Steps, 新增 Run with timeout 超时时间根据实际情况配置 Build Step选择 执行SHELL 填写一下命令&#xff0c;这个命令是docker中执行phpunit单元测试&#xff0c;请根据你的实际…

FPGA学习笔记之Nios II(一)简单介绍及新建工程及下载

系列文章目录 文章目录 系列文章目录前言QsysNios IIhello world 实例Platform DesignNios II程序设计 前言 利用Quartus中的Qsys工具&#xff0c;可以实现在FPGA里面跑嵌入式的功能 Qsys Altera 公司将主控制器、数字信号处理模块、存储器及其控制模块、各种接口协议等模块&…

亚马逊测评还能做吗?

只能说测评不是唯一的手段&#xff0c;但是推销量的一把好手。首先测评能让listing快速成长&#xff0c;短期内有望成为爆款&#xff0c;速度快&#xff0c;利润高&#xff0c;回款快。相对其他推广&#xff0c;测评无疑是有效&#xff0c;省培养listing的方法。其次新品前期太…

聊聊 JSON Web Token (JWT) 和 jwcrypto 的使用

哈喽大家好&#xff0c;我是咸鱼。 最近写的一个 Python 项目用到了 jwcrypto 这个库&#xff0c;这个库是专门用来处理 JWT 的&#xff0c;JWT 全称是 JSON Web Token &#xff0c;JSON 格式的 Token。 今天就来简单入门一下 JWT。 官方介绍&#xff1a;https://jwt.io/intr…

RH850F1KM-S4-100Pin_ R7F7016453AFP MCAL Gpt 配置

1、Gpt组件包含的子配置项 GptDriverConfigurationGptDemEventParameterRefsGptConfigurationOfOptApiServicesGptChannelConfigSet2、GptDriverConfiguration 2.1、GptAlreadyInitDetCheck 该参数启用/禁用Gpt_Init API中的GPT_E_ALREADY_INITIALIZED Det检查。 true:开启Gpt_…

JS核心语法【流程控制语句、函数】;DOM【查找元素、操作元素、事件】--学习JavaEE的day48

day48 JS核心技术 JS核心语法 继day47 注意&#xff1a;用到控制台输出、弹窗 流程控制语句 If else、For、For-in(遍历数组时&#xff0c;跟Java是否一样【java没有】)、While、Do while、break、continue 案例&#xff1a; 1.求1-100之间的偶数之和 <!DOCTYPE html> …

Android消息机制回顾(Handler、Looper、MessageQueue源码解析)

回顾&#xff1a; Android消息机制 Android消息机制主要指的是Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作机制。 介绍 通过Handler 消息机制来解决线程之间通信问题&#xff0c;或者用来切换线程。特别是在更新UI界面时&#xff0c;确保了线程间的数…