并发编程篇

2023-10-27

并发编程篇

线程基础

线程和进程的区别

面试官: 说一下线程和进程的区别?

候选人:

嗯,好~

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

并行与并发的区别

面试官: 聊一下并行和并发有什么区别?

候选人:

是这样的~~

现在都是多核CPU,在多核CPU下

并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU

并行是同一时间动手做多件事情的能力,4核CPU同时执行4个线程

线程创建的方式

面试官: 如果在Java中创建线程有哪些方式?

候选人:

在Java中一共有四种常见的创建方式,分别是:继承Thread类、实现runnable接口、实现Callable接口、线程池创建线程。通常情况下,我们项目中都会采用线程池的方式创建线程。

面试官: 好的,刚才你说的runnable 和 callable 两个接口创建线程有什么不同呢?

候选人:

是这样的~

最主要的两个线程一个是有返回值,一个是没有返回值的。

Runnable 接口run方法无返回值;Callable接口call方法有返回值,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果

还有一个就是,他们异常处理也不一样。Runnable接口run方法只能抛出运行时异常,也无法捕获处理;Callable接口call方法允许抛出异常,可以获取异常信息

在实际开发中,如果需要拿到执行的结果,需要使用Callable接口创建线程。调用FutureTask.get()可以得到返回值,此方法会阻塞主线程的继续往下执行,如果不调用不会阻塞。

面试官: run()和start()有什么区别?

候选人:

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

线程的状态

面试官: 线程包括哪些状态,状态之间是如何变化的?

候选人:

在JDK中的Thread类中的枚举State里面定义了6种线程的状态分别是:新建、可运行、终结、阻塞、等待和有时限等待六种。

关于线程的状态切换情况比较多。我分别介绍一下

当一个线程对象被创建,但还未被调用 start 方法时处于新建状态,调用了 start 方法,就会由新建进入可运行状态。如果线程内部代码已经执行完毕,由可运行进入终结状态。当然这些是一个线程正常执行情况。

如果线程获取锁失败后,由可运行进入 Monitor 的阻塞队列阻塞,只有当持锁线程释放锁时,会按照一定规则唤醒阻塞队列中的阻塞线程,唤醒后的线程进入可运行状态

如果线程获取锁成功后,但由于条件不满足,调用了 wait()方法,此时从可运行状态释放锁等待状态,当其它持锁线程调用 notify9() 或 notifyAll()方法,会恢复为可运行状态

还有一种情况是调用 sleep(long)方法也会从可运行状态进入有时限等待状态,不需要主动唤醒,超时时间到自然恢复为可运行状态

线程按顺序执行

面试官: 好的,我现在举一个场景,你来分析一下怎么做,新建T1、T2、T3 三个线程,如何保证它们按顺序执行?

候选人:

嗯~~,我思考一下(适当的思考或想一下属于正常情况,脱口而出反而太假[背诵痕迹])

可以这么做,在多线程种有多种方法让线程按特定顺序执行,可以用线程的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。

比如说:

使用join方法,T3调用T2,T2调用T1,这样就能确保T1就会先完成而T3最后完成

面试官: notify()和notifyAll()有什么区别?

候选人:

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

wait和sleep方法的不同

面试官: 嗯,好的,刚才你说的线程中的 wait 和 sleep 方法有什么不同呢?

候选人:

wait(),wait(long) 和 sleep(long) 的效果都是让当前线程暂时放弃 CPU 的使用权,进入阻塞状态。

不同点主要有三个方面:

第一:方法归属不同

sleep(long)是 Thread 的静态方法。而wait(),是 Object 的成员方法,每个对象都有

第二:醒来时机不同

线程执行sleep(long)会在等待相应毫秒后醒来,而wait()需要被 notify 唤醒,wait()如果不唤醒就一直等下去

第三:锁特性不同

wait 方法的调用必须先获取 wait 对象的锁,而sleep 则无此限制

wait 方法执行后会释放对象锁,允许其它线程获得该对象锁(相当于我放弃 cpu,但你们还可以用)

而sleep 如果在 synchronized 代码块种执行,并不会释放对象锁(相当于我放弃 cpu,你们也用不了)

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

面试官: 那如何停止一个正在运行的线程呢?

候选人:

有三种方式可以停止线程

第一:可以使用退出标志,使线程正常退出,也就是当run方法完成后线程终止,一般我们加一个标记

第二:可以使用线程的stop方法强行终止,不过一般不推荐,这个方法已作废

第三:可以使用线程的interrupt方法中断线程,内部其实也是使用中断标志来中断线程

我们项目种使用的话,建议使用第一种或第三种方式中断线程

线程安全

synchronized关键字的底层原理(基础回答)

面试官: 讲一下synchronized关键字的底层原理?

候选人:

嗯~~好的,

synchronized 底层使用的JVM级别的级别中的Monitor 来决定当前线程是否获得了锁,如果某一个线程获得了锁,在没有释放锁之前,其他线程是不能得到锁的。synchronized 属于悲观锁。

synchronized 因为需要依赖JVM级别的Monitor,相对性能也比较低。

面试官: 好的,你能具体说下Monitor 吗?

候选人:

monitor对象存在于每个Java对象的对象头中,synchronized 锁便是通过这种方式获取锁的,也是为什么Java对象中任意对象可以作为锁的原因

monitor内部维护了三个变量

  • WaitSet:保存处于Waiting状态的线程
  • EntryList:保存处于Blocked状态的线程
  • Owner:持有锁的线程

只有一个线程获取到的标志就是在monitor中设置了Owner,一个monitor中只能有一个Owner

在上锁的过程中,如果有其他线程也来抢锁,则进入EntryList 进行阻塞,当获得锁的线程执行完了,释放了锁,就会唤醒EntryList 中等待的线程竞争锁,竞争的时候是非公平的。

synchronized关键字的底层原理(进阶回答)

面试官: 好的,那关于synchronized 的锁升级的情况了解吗?

候选人:

嗯,知道一些(要谦虚)

Java中的synchronized有偏向锁、轻量级锁、重量级锁三种形式,分别对应了锁只被一个线程持有、不同线程交替持有锁、多线程竞争锁三种情况。

重量级锁:底层使用的Monitor实现,里面涉及到了用户态和内核态的切换、进程的上下文切换,成本较高,性能比较低。

轻量级锁:线程加锁的时间是错开的(也就是没有竞争),可以使用轻量级锁来优化。轻量级修改了对象头的锁标志,相对重量级锁性能提升很多。每次修改都是CAS操作,保证原子性

偏向锁:一段很长的时间内都只被一个线程使用锁,可以使用偏向锁,在第一次获得锁时,会有一个CAS操作,之后该线程再获取锁,只需要判断mark word中是否是自己的线程id即可,而不是开销相对较大的CAS命令

一旦锁发生了竞争,都会升级为重量级锁

JMM(Java内存模型)

面试官: 你谈谈 JMM(Java内存模型)

候选人:

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

你谈谈对CAS的理解

面试官: CAS 你知道吗?

候选人:

  • CAS的全称是:Compare And Swap(比较再交换);它体现的一种乐观锁的思想,在无锁状态下保证线程操作数据的原子性。
  • CAS使用到的地方很多:AQS框架、AtomicXXX类
  • 在操作共享变量的时候实用的自旋锁,效率上更高一些
  • CAS的底层是调用的Unsafe类中的方法,都是操作系统提供的,其他语言实现(C,C++)

面试官: 乐观锁和悲观锁的区别?

候选人:

  • CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃点亏再重试呗。
  • synchronized 是基于悲观锁的思想:最悲观的估计,得防着其他线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。

请谈谈你对volatile 的理解

面试官: 请谈谈你对 volatile 的理解?

候选人:

①保证线程间的可见性

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

②禁止进行指令重排序

指令重排:用volatile修饰共享变量会在读、写共享变量时加入不同的屏障,阻止其他读写操作越过屏障,从而达到阻止重排序的效果

什么是AQS

面试官: 什么是AQS?

候选人:

  • 是多线程中的队列同步器。是一种锁机制,它是作为一个基础框架使用的,像ReentrantLock、Semaphore都是基于AQS实现的
  • AQS内部维护了一个先进先出的双向队列,队列中存储的排队的线程
  • 在AQS内部还有一个属性state,这个state就相当于是一个资源,默认是0(无锁状态),如果队列中的有一个线程修改成功了state为1,则当前线程就相当于获取了资源
  • 在对state修改的时候使用的cas操作,保证多个线程修改的情况下原子性

ReentrantLock的实现原理

面试官: 好的,你刚才说了下synchronized它在高并发量的情况下,性能不高,在项目中该如何控制使用锁呢?

候选人:

嗯,其实,在高并发下,我们可以使用ReentrantLock来加锁。

面试官: 嗯,那你说下ReentrantLock的使用方式和底层原理?

候选人:

好的,ReentrantLock是一个可重入锁;调用 lock 方法获取了锁之后,再次调用 lock,是不会再阻塞,内部直接增加重入次数就行了,标识这个线程已经重复获取一把锁而不需要等待锁的释放。

ReentrantLock是属于juc包下的类,属于api层面的锁,跟synchronized一样,都是悲观锁。通过lock()用来获取锁,unlock()释放锁。

它的底层实现原理主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似

构造方法接受一个可选的公平参数(默认非公平锁),当设置为true时,表示公平锁,否则为非公平锁。公平锁的效率往往没有非公平锁的效率高。

面试官: 好的,刚才你说了CAS和AQS,你能介绍一下吗?

候选人:

好的。

CAS的全称是:Compare And Swap(比较再交换);它体现的一种乐观锁的思想,在无锁状态下保证线程操作数据的原子性。

  • CAS使用到的地方很多:AQS框架、AutomicXXX类
  • 在操作共享变量的时候使用的自旋锁,效率上更高一些
  • CAS的底层是调用的Unsafe类中的方法,都是操作系统提供的,其他语言实现

AQS的话,其实就一个jdk提供的类AbstractQueuedSynchronizer,是阻塞式和相关的同步器工具的框架。

内部有一个属性state来表示资源的状态,默认state等于0,表示没有获取锁,state等于1的时候才标明获取到了锁。通过cas机制设置state状态

在它的内部还提供了基于 FIFO 的等待队列,是一个双向列表,其中

  • tail 指向队列最后一个元素
  • head 指向队列中最久的一个元素

其实我们刚刚聊的ReentrantLock底层的实现就是一个AQS。

synchronized和Lock有什么区别

面试官: synchronized和Lock有什么区别 ?

候选人:

嗯~~,好的,主要有三个方面不太一样

第一,语法层面

  • synchronized 是关键字,源码在 jvm 中,用 c++ 语言实现,退出同步代码块锁会自动释放
  • Lock 是接口,源码由 jdk 提供,用 java 语言实现,需要手动调用 unlock 方法释放锁

第二,功能层面

  • 二者均属于悲观锁、都具备基本的互斥、同步、锁重入功能
  • Lock 提供了许多 synchronized 不具备的功能,例如获取等待状态、公平锁、可打断、可超时、多条件变量,同时Lock锁可以实现不同的场景,如ReentrantLock、ReentrantReadWriteLock

第三、性能层面

  • 在没有竞争时,synchronized 做了很多优化,如偏向锁、轻量级锁,性能不赖
  • 在竞争激烈时,Lock的实现通常会提供更好的性能

综合来看,需要根据不同的场景来选择不同的锁的使用。

死锁产生的条件以及死锁排查方案

面试官: 死锁产生的条件是什么 ?

候选人:

嗯,是这样的,一个线程需要同时获取多把锁,这时就容易发生死锁,举个例子来说:

t1 线程获得A对象锁,接下来想获取B对象的锁

t2 线程获得B对象锁,接下来想获取A对象的锁

这个时候t1线程和t2线程都在互相等待对方的锁,就产生了死锁

面试官: 那如果产生了这样的,如何进行死锁诊断 ?

候选人:

这个也容易,我们只需要通过jdk自动的工具就能搞定

我们可以先通过jps来查看当前Java程序运行的进程id

然后通过jstack来查看这个进程id,就能展示出来死锁的问题,并且,可以定位代码的具体行号范围,我们再去找到对应的代码进行排查就行了。

另外还有可视化工具jconsole、VisualV

聊一下ConcurrentHasp

本文作者: 接《集合相关面试题》

面试官: 那你能聊一下ConcurrentHashMap的原理吗 ?

候选人:

好的,

ConcurrentHashMap 是一种线程安全的高效Map集合,jdk1.7和1.8也做了很多调整。

  • JDK1.7的底层采用的是分段的数组+链表 实现
  • JDK1.8采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。

在jdk1.7中 ConcurrentHashMap 里面包含一个 Segment 数组。Segment 的结构和HashMap类似,是一种数组和链表结构,一个Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 的锁。

Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个 HashEntry 数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁

在jdk1.8中的 ConcurrentHashMap 做了较大的优化,性能提升了不少。首先是它的数据结构与jdk1.8的hashMap数据结构完全一致。其次是放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率得到提升。

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

面试官: 导致并发程序出现问题的根本原因是什么 ?

候选人:

  1. 原子性:synchronized、lock
  2. 内存可见性:volatile、synchronized、lock
  3. 有序性:volatile

**面试官:**好的,那该如何保证Java程序在多线程的情况下执行安全呢?

候选人:

嗯,刚才讲过了导致线程安全的原因,如果解决的话,jdk中也提供了很多的类帮助我们解决多线程安全的问题,比如:

  • JDK Atomic开头的原子类、synchronized、LOCK,可以解决原子性问题
  • synchronized、volatile、LOCK,可以解决可见性问题
  • Happens-Before 规则可以解决有序性问题

线程池

说一下线程池的核心参数(线程池的执行原理知道嘛)

面试官: 线程池的核心参数有哪些 ?

候选人:

在线程池中一共有7个核心参数:

  1. corePoolSize 核心线程数目 - 池中会保留的最多线程数
  2. maximumPoolSize 最大线程数目 - 核心线程 + 救急线程的最大数目
  3. keepAliveTime 生存时间 - 救急线程的生存时间,生存时间内没有新任务,此线程资源会释放
  4. unit 时间单位 - 救急线程的生存时间单位,如秒、毫秒等
  5. workQueue - 当没有空闲核心线程时,新来任务会加入此队列排队,队列满会创建救急线程执行任务
  6. threadFactory 线程工厂 - 可以定制线程对象的创建,例如设置线程名字、是否是守护线程等
  7. handler 拒绝策略 - 当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略

在拒绝策略中又有4种拒绝策略

当线程数过多以后,第一种是抛线程、第二种是由调用者执行任务、第三是丢弃当前的任务,第四是丢弃最早排队任务。默认是直接抛异常。

面试官:线程池的执行原理知道吗?

候选人

嗯~,它是这样的

首先判断线程池里的核心线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队 列里。如果工作队列满了,则判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任 务。如果已经满了,则交给拒绝策略来处理这个任务。

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

面试官: 线程池有哪些常见的阻塞队列 ?

候选人:

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

  1. ArrayBlockingQueue:基于数组结构的有界阻塞队列,FIFO。
  2. LinkedBlockingQueue:基于链表结构的有界阻塞队列,FIFO。
  3. DelayedWorkQueue:是一个优先级队列,它可以保证每次出队的任务都是当前队列中执行时间最靠前的
  4. SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移出操作

ArrayBlockingQueueLinkedBlockingQueue的区别

ArrayBlockingQueue:强制有界、底层是数组、提前初始化 Node 数组、Node需要是提前创建好的、一把锁

LinkedBlockingQueue:默认无界,支持有界、底层是链表、是懒惰的,创建节点的时候添加数据、入队会生成新 Node、两把锁(头尾)

如何确定核心线程数

面试官: 如何确定核心线程池呢 ?

候选人:

是这样的,我们公司当时有一些规范,为了减少线程上下文的切换,要根据当时部署的CPU核数来决定,我们规则是:CPU核数 + 1就是最终的核心线程数
在这里插入图片描述

线程池的种类有哪些

面试官: 线程池的种类有哪些 ?

候选人:

嗯!是这样

在jdk中默认提供了4种方式创建线程池

第一个是:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

第二个是:newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

第三个是:newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。

第四个是:newSingleThreadExecutor创建了一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。

为什么不建议用Executors创建线程池

面试官: 为什么不建议用Executors创建线程池 ?

候选人:

好的,其实这个事情在阿里提供的开发手册《Java开发手册-嵩山版》中也提到了

主要原因是如果使用Executors创建线程池的话,它允许的请求队列默认长度是Integer.MAX_VALUE,这样的话,有可能导致堆积大量的请求,从而导致OOM(内存溢出)。

所以,我们一般推荐使用ThreadPoolExecutor来创建线程池,这样可以明确规定线程池的参数,避免资源的耗尽。

使用场景

ES数据批量导入、数据汇总、异步线程

面试官: 你在项目中哪里用了多线程 ?

候选人:

嗯~~,我想一下当时的场景[根据自己简历上的模块设计多线程场景]

参考场景一:

es数据批量导入

在我们项目上线前,我们需要把数据量的数据一次性的同步到es索引库中,但是当时的数据好像是1000万左右,一次性读取数据肯定不行(omm异常),如果分批执行的话,耗时也太久了。所以,当时我就想到可以使用线程池的方式导入,利用CountDownLatch+Future来控制,就能大大提升导入的时间。

参考场景二:

在我做的那个xx电商网站的时候,里面有一个数据汇总的功能,在用户下单之后需要查询订单信息,也需要获得订单中的商品详细信息(可能是多个),还需要查看物流发货信息。因为它们三个对应的分别三个微服务,如果一个一个的操作的话,互相等待的时间比较长。所以,我当时就想到可以使用线程池,让多个线程同时处理,最终再汇总结果就可以了,当然里面需要用到Future来获取每个线程执行之后的结果才行。

参考场景三:

《黑马头条》项目中使用的

我当时做了一个文章搜索的功能,用户输入关键字要搜索文章,同时需要保存用户的搜索记录(搜索历史),这块我设计的时候,为了不影响用户的正常搜索,我们采用的异步的方式进行保存的,为了提升性能,我们加入了线程池,也就说在调用异步方法的时候,直接从线程池中获取线程使用

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

面试官: 如何控制某一个方法允许并发访问线程的数量 ?

候选人:

嗯~~,我想一下

在jdk中提供了一个Semaphore类(信号量)

它提供了两个方法,semaphore.acquire()请求信号量,可以限制线程的个数,是一个正数,如果信号量是-1,就代表已经用完了信号量,其他线程需要阻塞了

第二个方法是semaphore.release(),代表是释放了一个信号量,此时信号量的个数+1

其他

谈谈你对ThreadLocal的理解

面试官: 谈谈你对ThreadLocal的理解 ?

候选人:

嗯,是这样的~~

ThreadLocal主要功能有两个,第一个是可以实现资源对象的线程隔离,让每个线程各用各的资源对象,避免争用引发的线程安全问题,第二个是实现了线程内的资源共享

面试官: 好的,那你知道ThreadLocal的底层原理实现吗?

候选人:

嗯,知道一些~

在ThreadLocal内部维护了一个一个ThreadLocalMap类型的成员变量,用来存储资源对象

当我们调用set方法,就是以ThreadLocal自己作为key,资源对象作为value,放入当前线程的ThreadLocalMap集合中

当调用get方法,就是以ThreadLocal自己作为key,到当前线程中查找关联的资源值

当调用remove方法,就是以ThreadLocal自己作为key,移出当前线程相关联的资源值

面试官: 好的,那关于ThreadLocal会导致内存溢出这个事情,了解吗?

候选人:

嗯,我之前看过源码,我想一下~~

是因为ThreadLocalMap中的key被设计为弱引用,它是被动的被GC调用释放key,不过关键的是只有key可以得到内存释放,而value不会,因为value是一个强引用。

在使用ThreadLocal时都把它作为静态变量(即强引用),因此无法被动依靠GC回收,建议主动地remove释放key,这样就能避免内存溢出

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

并发编程篇 的相关文章

  • 检查发送到网页的请求数

    我正在编写一个 Java 多线程应用程序 它可以访问不同 Web 服务器的数百万个 有时甚至数十亿个 URL 这个想法是检查这些 URL 是否给出有效的 200OK 响应或 404 其他代码 我如何知道我的程序是否不会在他们的服务器上造成高
  • 帮助我避免 JPA、Hibernate 和 MySQL 的连接超时

    我正在使用 JPA Hibernate 作为提供者 Glassfish 和 MySQL 开发中一切都运行良好 但是当我将应用程序部署到测试服务器并让它运行 大部分空闲 过夜时 我通常会在早上遇到这样的情况 2011 03 09T15 06
  • Active MQ - HelloWorld 示例异常

    我正在尝试运行 hello world 示例在这里找到 http activemq apache org hello world html I added activemq all 5 5 1 jar已经到图书馆了 它构建成功 但出现以下警
  • 从字符串生成密钥?

    我需要从字符串生成一个密钥 以便我始终可以从同一字符串创建相同的密钥 具体来说是一个Key对象 这样我就可以用它来创建Cipher进而创建SealedObject 这在 Java 中可行吗 我应该考虑什么类 方法组合才能做到这一点 对于 A
  • 使用 Hibernate Dialect 设置表字符集/排序规则?

    我使用 Hibernate MySQLInnoDB Dialect 来生成 DDL hibernate cfg xml
  • 按文件名过滤 eclipse 中的警告

    我们使用 Eclipse 进行 Java 开发 并使用 Maven 将 JSP 编译成 servlet 以便在嵌入式 Jetty 实例中使用 这意味着要从 Eclipse 运行该项目 我必须包含 target jsp source 作为源文
  • SwingWorker 在另一个 SwingWorker 的 did 方法中

    首先 我需要通知您 我正在尽最大努力学习如何用 Java 编写代码 虽然有点困难 但我相信我能做到 我过去提交了几个有关 SwingWorkers 等的问题 每一个我都以为我已经做到了 但后来发现我仍然需要学习 希望这一次不是那样的一次 话
  • Java 中的 MP4 容器编写器

    我想找到一个免费的 Java MP4 容器 编写器 我不需要编码器 只需要能够根据预期值写入正确原子的编码器 Bonus对于这样一个库 也可以编写 有效 F4V 我更喜欢纯 Java 解决方案 而不是使用 JNI 或外部可执行文件的解决方案
  • 反应式 Spring Webflux REST 控制器内部重定向

    我正在为 spring 反应项目创建简单的控制器服务器 在设置重定向到另一个位置时 我在调用时发现错误http localhost 8080 There was an unexpected error type Internal Serve
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • Java 不可变对象 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在学习不变性的概念 据我了解 一旦创建对象 不可变对象就无法更改其值 但我不明白不可变对象的以下用途 They are 自动是线程
  • 获取包中声明的所有 Java 类的名称

    我正在编写一个功能 它将有助于将类放入我的程序的某个包中 另外 我只想要子类某个类的类 我需要这些类才能调用它们的静态方法 有没有一种自动的方法来做到这一点 如果是的话 速度慢吗 如果我不清楚 我想要的是这样的 ArrayList
  • 如何在Java中模拟引用传递?

    我是一个十足的 Java 菜鸟 我知道 Java 将所有参数视为按值传递 并且还有其他几个线程人们对此进行了解释 例如 在 C 中我可以这样做 void makeAThree int n n 3 int main int myInt 4 m
  • javax.xml.bind.JAXBException: 类 *** 及其任何超类在此上下文中均未知

    我正在尝试通过 REST Web 服务传递对象 以下是我的课程 使用一些示例代码解释了我需要的功能 Rest Web 服务类方法 POST Path find Consumes MediaType APPLICATION FORM URLE
  • Java 验证日期为 yyyyMMddHHmmss

    我想在java中验证给定的日期格式为yyyyMMddHHmmss 状况 应符合格式 yyyyMMddHHmmss 它应该验证当前日期 它应该验证与当前小时有 3 小时或 3 小时差异的小时数 如果满足所有三个条件 Java 方法应返回 tr
  • while 之后无法访问的语句[重复]

    这个问题在这里已经有答案了 我只是修改代码 在以下代码中出现错误 int x 1 System out println x x while true x System out println x x 错误在最后一行 我可以知道错误 错误 无
  • ASTParser:解析绑定后查找声明节点

    我创建了一个启用了绑定的 AST 当我稍后解析绑定时 我得到了一个有效的 ITypeBinding 但是 当我想要获取绑定的声明 Node 时 它 总是返回 null 除非 ITypeBinding 在 sourceFile 中声明 这是我
  • Struts2中的变量声明

    Struts2中如何声明变量并为该变量赋值 使用设置标签
  • 如何列出Resources文件夹中的所有文件(java/scala)

    我正在编写一个函数 需要访问资源中的文件夹 并循环遍历所有文件名 如果这些文件符合条件 则加载这些文件 new File getClass getResource images sprites getPath listFiles 返回空指针
  • 使用正则表达式匹配阿拉伯文文本

    我试图使用正则表达式仅匹配阿拉伯语文本 但出现异常 这是我的代码 txt matches P Arabic 这是例外情况 线程 main 中的异常 java util regex PatternSyntaxException 索引 9 附近

随机推荐

  • SQLyog的免费使用方式

    1 删除注册表 会继续使用30天 输入 regedit 进入注册表 找到注册表 HEYK CURRENT USER Software FCE28CE8 D8CE 4637 9BC7 93E4C0D407FA 下的InD保存着SQLyog的使
  • Windows10下超详细Mysql安装

    目录 0 前言 1 下载mysql 2 开始安装 3 验证安装 4 环境变量配置 0 前言 Mysql简介 MySQL是一种开源的关系型数据库管理系统 RDBMS 它使用SQL 结构化查询语言 语言进行数据的存储和访问 MySQL的设计目标
  • U盘启动重装系统报cdboot:couldn't find ntldr 错误

    进BIOS把硬盘格式从IDE改为AHCI二 硬盘主MBR引导损坏 要用PE启动盘进行修复引导 解决方法 在PE打开分区工具Disk Genius点硬盘点重建主引导记录MBR
  • 微信小程序之30分钟学会开发小程序(小程序总览)

    一 注册小程序账号 下载IDE 1 官网注册https mp weixin qq com 并下载IDE 2 官方文档一向都是最好的学习资料 注意 1 注册账号之后会有一个appid 新建项目的时候需要填上 不然很多功能是用不了的 比如不能预
  • 两个真实线上升级故障让你彻底搞懂package.json中的脱字符(^)

    大厂技术 高级前端 Node进阶 点击上方 程序员成长指北 关注公众号 回复1 加入高级Node交流群 作者 掘金干货君 原文 https juejin cn post 7121520457760653349 package json 相信
  • object标签上悬浮div标签,可拖拽,播放rtsp视频

    object上方悬浮div并实现拖拽 云台控制等操作 注意 1 在static目录下创建video html 2 必须安装2 2 1 win32版本的vlc插件 3 vlc安装文件 链接 https pan baidu com s 1yQJ
  • 日志聚合工具loki

    目录 1 loki是什么 2 loki特点 3 loki组成 4 loki安装 4 1 添加helm的chart库 4 2 安装loki及promtail 4 3 安装grafana 5 配置和使用 6 日志选择和过滤 6 1 日志选择器
  • ROS Melodic 安装时所遇到的问题及解决方法

    文章目录 参考教程 所遇到的问题 1 sudo rosdep init 2 ERROR default sources list file already exists etc ros rosdep sources list d 20 de
  • 接口入参格式为x-www-form-urlencoded 的处理

    一般情况下接口入参数格式要求是JSON通用格式 但有些时候接口入参数要求是x www form urlencoded格式 这种格式前端就不能传递JSON格式数据了 如果传递JSON数据的话 接口会报异常 下面对此种情况做解释处理 1 接口入
  • Elasticsearch 配置内存量

    场景 由于配置es之后服务器内存负载过高 原因 初步原因是es内存暂用过高 处理 修改es的配置文件jvm options 根据服务器情况一般是配置服务器内存的一半
  • 手残,双硬盘(SSD+HDD)双系统(Win10+ubuntu)用easyBCD删除win10引导项怎么办?戳这里

    问题描述 博主处女座 电脑双硬盘 固态 机械 因为学习需要 装了双系统 Win10 Ubuntu 这个也是费了不少功夫才成功 不知道怎么装的可以看我这个http blog csdn net x1825048925 article detai
  • 怎样的架构设计才是真正的数据仓库架构

    在各个网站和论坛 一说到数据仓库 基本都想到了 ETL DW OLAP 一说到数据仓库设计 就是按照行业规范和客户需求调研 设计主题 然后设计对应的 事实表 维表 但是 这就是真正的数据仓库总体设计么 关于上面说的主题设计 以及前端展现 这
  • cfssljson详解1

    一 cfssljson简介 大多数cfssl命令的输出内容都是JSON格式的 而cfssljson工具可以将这些JSON格式的输出内容作为输入内容 并按照key键 key certificate CSR and bundle 将之区分然后输
  • 机器学习-决策树算法ID3实现,含例子(红酒分类)

    决策树原理实现代码如下所示 参考自机器学习实践 Peter Harrington import math x 0 1 no 0 1 no 1 0 no 1 1 yes 1 1 no 1 1 no 1 1 maybe 1 1 maybe 1
  • 手把手教你搭建SpringCloudAlibaba项目

    SpringCloud Alibaba全集文章目录 零 手把手教你搭建SpringCloudAlibaba项目 一 手把手教你搭建SpringCloud Alibaba之生产者与消费者 二 手把手教你搭建SpringCloudAlibaba
  • 数据结构——AOE与算法——关键路径的计算

    AOE图 节点表示事件 弧表示活动 弧的权重表示活动进行的时间 关键路径 在AOE网中 从起始点到终点具有最大路径长度的一条路径被称为关键路径 算法思路 1 利用拓扑排序求出AOE网的一个拓扑序列 2 从拓扑排序的序列的第一个顶点 源点 开
  • 设计模式的 C++ 实现---策略模式

    前文回顾 单例模式 一 单例模式 二 观察者模式 简单工厂模式 工厂方法模式 一 工厂方法模式 二 抽象工厂模式 一 抽象工厂模式 二 原型模式 外观模式 中介者模式 代理模式 装饰者模式 前言 所谓策略即解决一件事情的算法 或者方法 是一
  • intel至强服务器芯片制程,64核自研芯片性能提升7倍,追平英特尔至强

    不久之前 英特尔发布了至强铂金8284处理器 单个内核拥有高达28核心56线程 刷新了业界顶尖水平 事实上 在服务器级处理器中 英特尔的产品一向具有重要的地位 它的服务器芯片不仅技术先进 而且耐用程度优质 能耗控制良好 可以说是服务器必备产
  • AJAX请求返回流 下载Excel文件

    AJAX请求返回流 下载Excel文件 模拟请求 var xhr new XMLHttpRequest 文件名称 var fileName 1 xls xhr open POST http 127 0 0 1 8001 Api Downlo
  • 并发编程篇

    并发编程篇 线程基础 线程和进程的区别 面试官 说一下线程和进程的区别 候选人 嗯 好 进程是正在运行程序的实例 进程中包含了线程 每个线程执行不同的任务 不同的进程使用不同的内存空间 在当前进程下的所有线程可以共享内存空间 线程更轻量 线