重庆网站建设子沃科技,网站建设验收单模板,ai智能设计logo免费,网页设计教程电商文章目录 1.HashSet如何检查重复2.comparable和Comparator区别3.ConcurrentHashMap和Hashtable区别4.线程和进程5.并发与并行的区别6.为什么使用多线程7.使用多线程可能带来问题8.线程的生命周期和状态9.什么是上下文切换10.线程死锁11.产生死锁四个条件12.如何避免死锁 1.Hash… 文章目录 1.HashSet如何检查重复2.comparable和Comparator区别3.ConcurrentHashMap和Hashtable区别4.线程和进程5.并发与并行的区别6.为什么使用多线程7.使用多线程可能带来问题8.线程的生命周期和状态9.什么是上下文切换10.线程死锁11.产生死锁四个条件12.如何避免死锁 1.HashSet如何检查重复
当你把对象加入HashSet时HashSet会先计算对象的hasdcode值来判断对象加入的位置同时也会与其他加入的对象的hashcode值作比较如果没有相符的hashcodeHashSet会假设对象没有重复出现。但是如果发现有相同的hashcode值的对象这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同HashSet就不会让加入操作成功。
2.comparable和Comparator区别
comparable接口实际上是出自java.lang包它有一个compareTo(Object obj)方法用来排序。comparator接口实际上是出自java.util包它有一个compare(Object obj1Object obj2)方法用来排序。
3.ConcurrentHashMap和Hashtable区别
ConcurrentHashMap和Hashtable的区别主要体现在实现线程安全的方式上不同。
底层数据结构JDK1.7的ConcurrentHashMap底层采用分段数组链表实现JDK1.8采用的数据结构跟HashMap1.8的结构一样数组链表/红黑二叉树。Hashtable的JDK1.8之前的HashMap的底层数据结构类似都是采用数组链表的形式数组是HashMap的主体链表则是主要为了解决哈希冲突而存在的。实现线程安全的方式在JDK1.7的时候ConcurrentHashMap分段锁对整个桶数组进行了分割分段Segment每一把锁只锁容器其中的一部分数据多线程访问容器里不同的数据段的数据就不会存在锁竞争提高并发访问率。到了JDK1.8的时候已经摒弃了Segment的概念而是直接用Node数组链表红黑树的数据结构来实现并发控制使用synchronized和CAS来操作。JDK1.6以后对synchronized锁做了很多优化整个看起来像是优化过且线程安全的HashMap虽然在JDK1.8中还能看到Segment的数据结构但是已经简化了属性只是为了兼容低版本Hashtable使用synchronized来保证线程安全效率非常低下。当一个线程访问同步方法时其他线程也访问同步方法可能会进入阻塞或轮询状态如使用put添加元素另一个线程不能使用put添加元素也不能使用get竞争会越来越激烈效率越低。
4.线程和进程
进程 进程是程序的一次执行过程是系统运行程序的基本单位因此进程是动态的。系统运行一个程序即是一个进程从创建、运行到消亡的过程。 在Java中当我们启动main函数时其实就是启动了一个JVM的进程而main函数所在的线程就是这个进程中的一个线程也称主线程。 线程 线程与进程类似但线程是一个比进程更小的执行单位。一个进程在其执行过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源但每个线程有自己的程序计数器、虚拟机栈和本地方法栈所以系统在产生一个线程或是在各个线程之间切换工作时负担要比进程小得多因此线程被称为轻量级进程。 区别 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的而各线程则不一定因为同一进程中的线程极有可能会相互影响。线程执行开销小但是不利于资源的管理和保护而进程相反。
5.并发与并行的区别
并发同一时间段多个任务都在执行单位时间内不一定同时执行。并行单位时间内多个任务同时执行。
6.为什么使用多线程
先从总体上来说
从计算机底层来说线程可以比作是轻量级的进程是程序执行的最小单位线程间的切换和调度的成本远远小于进程。另外多核CPU时代意味着多个线程可以同时运行这减少了线程上下文切换的开销。从当代互联网发展趋势现在的系统动不动就要求百万级甚至千万级的并发量而多线程并发编程正是开发高并发系统的基础利用好多线程机制可以大大提高系统整体的并发能力以及性能。 深入计算机底层来说单核时代单核时代多线程主要是为了提高CPU和IO设备的综合利用率。多核时代多核时代多线程是为了提高CPU和IO设备的综合利用率。
7.使用多线程可能带来问题
并发编程目的就是为了能够提高程序的执行效率提高程序运行速度但是并发编程并不总是能提高程序运行速度的而且并发编程可能会遇到很多问题比如内存泄漏、上下文切换、死锁还有受限于硬件和软件的资源闲置问题。
8.线程的生命周期和状态
状态名称说明NEW初始状态线程被构建但是还没有调用start()方法RUNNABLE运行状态Java线程将操作系统中的就绪和运行两种状态笼统地称为运行中BLOCKED阻塞状态表示线程阻塞于锁WAITING等待状态表示线程进入等待状态进入该状态表示当前线程需要等待其他线程做出一些特定动作通知或中断TIMED_WAITING超时等待状态该状态不同于WAITING它是可以在指定的时间自行返回的TERMINATED终止状态表示当前线程已经运行完毕
线程创建之后处于NEW(新建)状态调用start()方法后开始运行线程这时候处于READY(可运行)状态。可运行状态的线程获得CPU时间片(timeslice)后就处于RUNNING(运行)状态。当线程执行wait()方法之后线程进入WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能返回到运行状态而TIME_WAITING(超时等待)状态相当于在等待状态的基础上增加了超时限制比如通过sleep(long millis)方法或wait(long millis)方法可以将Java线程置于TIMED WAITING状态。当超时时间到达后Java线程将会返回到RUNNABLE状态。当线程调用同步方法时在没有获取到锁的情况下线程将会进入**BLOCKED(阻塞)状态。线程在执行Runnable的run()方法之后将会进入到TERMINATED(终止)**状态。
9.什么是上下文切换
多线程编程中一般线程的个数都大于CPU核心的个数而一个CPU核心在任意时刻只能被一个线程使用为了让这些线程都能得到有效执行CPU采取的策略是为每个线程分配时间片并轮转的形式。当一个线程的时间片用完的时候就会重新处于就绪状态让给其他线程使用这个过程就属于一次上下文切换。
概括来说当前任务在执行完CPU时间片切换到另一个任务之前会保存自己的状态以便下次再切换回这个任务时可以再加载这个人物的状态。任务从保存到再加载的过程就是一次上下文切换。
10.线程死锁
线程死锁描述的就是多个线程同时被阻塞它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞因此程序不可能正常终止。
11.产生死锁四个条件
互斥条件该资源任意一个时刻只由一个线程占用。请求与保持条件一个进程因请求资源而阻塞时对已获得的资源保持不放。不剥夺条件线程已获得的资源在未使用完之前不能被其他线程强行剥夺只有自己使用完毕后才释放资源。循环等待条件若干进程之间形成一种头尾相接的循环等待资源关系。
12.如何避免死锁
为了避免死锁只要破坏产生死锁的四个条件中的一个
破坏互斥条件这个条件我们没有办法破坏因为我们用锁本来就是想让他们互斥临界资源需要互斥访问。破坏请求与保持条件一次性申请所有的资源。破坏不剥夺条件占用部分资源的线程进一步申请其他资源时如果申请不到可以主动释放它占有的资源。破坏循环等待条件靠按序申请资源来预防。按某一顺序申请资源释放资源则反序释放。