首页 > 编程知识 正文

补充维生素C,少女前线数据补丁如何使用

时间:2023-05-04 00:22:10 阅读:154668 作者:437

juc补充jucHashMap和HashTable的区别是什么? ConcurrentHashMap和HashTable有什么区别? (一定要问)你知道ConcurrentHashMap的具体实现吗? HashMap的长度为什么是2的幂? List和Set的区别是什么? List、Set和Map的初始容量和负载因子是什么? Comparable接口和Comparator接口的区别是什么? 多线程和单线程的区别和联系如何指定多个线程的执行顺序? 线程和进程的区别是什么? (必填)多线程死锁发生的四个先决条件? sleep (和wait ) n )、wait )的区别是什么? synchronized关键词是什么? volatile关键字ThreadLocal (线程局部变量)关键字了解线程池吗? (必考)线程池的基础原理juc包(参加了几次必考) ) ) ) ) )。

juc HashMap和HashTable的区别是什么?

a ) HashMap不考虑同步,线程不安全; HashTable使用同步关键字,是线程安全的。前者允许空值作为Key; 后者不允许空值作为密钥。

ConcurrentHashMap和HashTable有什么区别? (一定要听) ConcurrentHashMap结合了HashMap和HashTable两者的优势。 HashMap没有考虑同步,插入时没有考虑同步。 1.8以前为插头法,1.8以后为插尾法(虽然不容易出现环形链表,但容易发生数据丢失)。 尽管HashTable考虑了同步问题,但每次执行同步时,HashTable都必须锁定整个结构。 具体来说,this锁定这里。 ConcurrentHashMap锁定方式在粒度稍小的同时,将Hash表分成16个桶(缺省值),get、put、remove等常用操作只锁定当前需要的桶。

你知道ConcurrentHashMap的具体实现吗? a )该类包含两个静态内部类HashEntry和Segment; 前者用于封装映射表的键值对,后者用于起到锁定的作用

Segment是一个可重新装入的锁ReentrantLock,每个Segment保护一个HashEntry数组中的元素。 更改HashEntry数组中的数据时,必须首先获取相应的Segment锁。

HashMap的长度为什么是2的幂? 通过对Key的hash值和length1进行运算,实现了当前的Key定位,通过2的幂可以减少碰撞(碰撞)的次数,提高了HashMap查询的效率。 如果length是2的幂,则length1变换为二进制必须是11111…的形式,h的二进制和操作效率非常快,不浪费空间; 如果length不是2的幂,例如,length为15,则length1为14,相应的二进制为1110,并且在h和操作中,最后一位变为0,并且,0001,0011,0101,1001,1011,0111,11111

List和Set的区别是什么? a ) List元素有序且可以重复; Set元素是无序的,不能重复。

List、Set和Map的初始容量和负载因子是什么? a. ListArrayList的初始容量为10; 加载因子为0.5; 扩展容量:原始容量的0.5倍1; 一次扩张后的长度为16。 Vector的初始容量为10,加载因子为1。 容量增量为原始容量的1倍,例如Vector的容量为10,扩展容量后容量为20。

b. SetHashSet初始容量为16,加载因子为0.75; 容量的增量为原始容量的1倍,例如,HashSet的容量为16,一次容量扩展后的容量为32。

c. MapHashMap初始容量16,测压因子0.75; 扩张量为原容量的1倍; 例如,HashMap的容量为16,一次容量扩展后的容量为32。 加载因子按泊松分布计算。 为什么会变成这样呢,因为这是实际操作,所以编程被大量实践。

Comparable接口和Comparator接口的区别是什么? 答案:

前者很简单,但如果需要重新定义比较类型,则需要修改源代码。

后者不需要修改源代码,而是定制比较器,实现个性化的比较方法。

多线程与单线程的区别和联系答案:单核CPU将CPU划分为较小的时间片,每个时间点只能运行一个线程。 从微观上按顺序占有CPU的结构。 多线程会在线程上下文之间切换,从而降低程序的执行速度。 这意味着,采用具有两个线程的进程,一个线程的进程执行所需的时间比两次执行的时间长。 结论采用多线程不会提高程序的运行速度,反而会降低速度,但对用户来说可以减少用户的响应时间。

如何指定多个线程的执行顺序? 解析:面试官举例,如何让10个线程按顺序打印012345678

9?(写代码实现)答:设定一个 orderNum,每个线程执行结束之后,更新 orderNum,指明下一个要执行的线程,并且唤醒所有的等待线程。在每一个线程的开始,要 while 判断 orderNum 是否等于自己的要求值!不是,则 wait,是则执行本线程。

线程和进程的区别是什么(必考)

答:进程是一个“执行中的程序”,是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,一个进程中拥有多个线程,线程之间共享地址空间和其他资源(因此通信和同步等操作线程比进程更加容易)线程上下文的切换比进程上下文切换要快很多:进程切换时,涉及到当前进程的 CPU 环境的保存和新被调度运行进程的 CPU 环境的设置;线程切换仅需要保存和设置少量的寄存器内容,不涉及存储管理方面的操作。

多线程产生死锁的 4 个必要条件?

答:互斥条件:一个资源每次只能被一个线程使用请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系
资源有限,循环等待,请求保持,不可剥夺

接问:如何避免死锁?(经常问)答:指定获取锁的顺序,举例如下:比如某个线程只有获得 A 锁和 B 锁才能对某资源进行操作,在多线程条件下,如何避免死锁?获得锁的顺序是一定的,比如规定,只有获得 A 锁的线程才有资格获取 B 锁,按顺序获取锁就可以避免死锁!
线程活跃态:活锁和饥饿,死锁
饥饿:线程一直得不到执行的机会

sleep( ) 和 wait(n)、wait( ) 的区别是什么?

答:sleep() 方法:是 Thread 类的静态方法,当前线程将睡眠 n 毫秒,线程进入阻塞状态。当睡眠时间到了,会解除阻塞,进行可运行状态,等待 CPU 的到来(睡眠不释放锁,如果有的话)。wait() 方法:是 Object 的方法,必须与 synchronized 关键字一起使用,线程进入阻塞状态,当 notify 或者 notifyall 被调用后,会解除阻塞。但是,只有重新占用互斥锁之后才会进入可运行状态。睡眠时,释放互斥锁。

synchronized 关键字是什么?

答:底层实现:进入时,执行 monitorenter,将计数器 +1,释放锁 monitorexit 时,计数器 −1;当一个线程判断到计数器为 0 时,则当前锁空闲,可以占用;反之,当前线程进入等待状态。含义:(monitor 机制)Synchronized 是在加锁,加对象锁。对象锁是一种重量锁(Monitor),Synchronized 的锁机制会根据线程竞争情况在运行时会有偏向锁(单一线程)、轻量锁(多个线程访问 Synchronized 区域)、对象锁(重量锁,多个线程存在竞争的情况)、自旋锁等,该关键字是一个几种锁的封装。

volatile 关键字

答:该关键字可以保证可见性不保证原子性。功能:主内存和工作内存,直接与主内存产生交互,进行读写操作,保证可见性禁止 JVM 进行的指令重排序解析:关于指令重排序的问题,可以查阅 DCL 双检锁失效相关资料。

ThreadLocal(线程局部变量)关键字

答:当使用 ThreadLocal 维护变量时,其为每个使用该变量的线程提供独立的变量副本,因此每一个线程都可以独立改变自己的副本,而不会影响其他线程对应的副本。ThreadLocal 内部实现机制:每个线程内部都会维护一个类似 HashMap 的对象,称为 ThreadLocalMap,里边会包含若干的 Entry(K-V 键值对),相应的线程被称为这些 Entry 的属主线程。Entry 的 Key 是一个 ThreadLocal 实例,Value 是一个线程特有对象。Entry 的作用是:为其属主线程建立起一个 ThreadLocal 实例与一个线程特有对象之间的对应关系。Entry 对 Key 的引用是弱引用;Entry 对 Value 的引用是强引用。

对线程池有了解吗?(必考)

线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出在务来执行。
答:java.util.concurrent.ThreadPoolExecutor 类就是一个线程池。客户端调用 ThreadPoolExecutor.submit(Runnable task) 提交任务,线程池内部维护的工作者线程的数量就是该线程池的线程池大小,有 3 种形态:当前线程池大小,表示线程池中实际工作者线程的数量;最大线程池大小(maxinumPoolSize),表示线程池中允许存在的工作者线程的数量上限;核心线程大小(corePoolSize),表示一个不大于最大线程池大小的工作者线程数量上限。如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队;如果运行的线程等于或者多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不是添加新线程;如果无法将请求加入队列,即队列已经满了,则创建新的线程,除非创建此线程超出 maxinumPoolSize,在这种情况下,任务将被拒绝。

线程池底层原理

1.在创建了线程池后,等待提交过来的任务请求。
2.当调用execute()方法添加一个请求任务时,线程池会做如下判断:
2.1如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;
2.2如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务成入队列;
2.3如果这时候队列满了且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
2.4如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行。
3.当一个线程完成任务时,它会从队列中取下一个任务来执行。
4.当一个线程无事可做超过一定的时间(keepAliveTime)时,线程池会判断:
如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后它最终会收缩到corePoolSize的大小。

juc包(必考考了几次了)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。