SynchronizedMap和ConcurrentHashMap有什么区别?
- SynchronizedMap()和Hashtable一样 , 实现上在调用map所有方法时 , 都对整个map进行同步 。而 ConcurrentHashMap的实现却更加精细 , 它对map中的所有桶加了锁 。所以 , 只要有一个线程访问 map , 其他线程就无法进入map , 而如果一个线程在访问ConcurrentHashMap某个桶时 , 其他线程 , 仍然可以对map执行某些操作 。
- 所以 , ConcurrentHashMap在性能以及安全性方面 , 明显比Collections.synchronizedMap()更加有优势 。同时 , 同步操作精确控制到桶 , 这样 , 即使在遍历map时 , 如果其他线程试图对map进行数据修改 , 也不会抛出ConcurrentModi?cationException。
- execute()方法 , 它的返回类型是void , 任务执行完后 , 没有返回值结果 , 它定义在Executor接口中 。
- submit()方法 , 它可以返回持有计算结果的Future对象 , 它定义在ExecutorService接口中 , 它扩展了Executor接口 。
- synchronized关键字解决的是多个线程之间访问资源的同步性 , synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能 有一个线程执行 。
- 在 Java 早期版本中 , synchronized属于重量级锁 , 效率低下 , 因为监视器锁(monitor)是依赖于底层的操作系统的 Mutex Lock 来 实现的 , Java 的线程是映射到操作系统的原生线程之上的 。
- 如果要挂起或者唤醒一个线程 , 都需要操作系统帮忙完成 , 而操作系统实现线程之间的切换时需要从用户态转换到内核态 , 这个状态之间的 转换需要相对比较长的时间 , 时间成本相对较高 , 这也是为什么早期的synchronized 效率低的原因 。
- 在 Java 6 之后 Java 官方对从 JVM 层面对synchronized 较大优化 , 所以现在的 synchronized 锁效率也优化得很不错了 。JDK1.6对锁的实现引入了大量的优化 , 如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销 。
- 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后 , 那么就具备了两层语义: 保证了不同线程对这个变量进行操作时的可见性 , 即一个线程修改了某个变量的值 , 这新值对其他线程来说是立即可见的 。
- 禁止进行指令重排序 。volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的 , 需要从主存中读取;synchronized则是锁定当前变量 , 只有当前线程可以访问该变量 , 其他线程被阻塞住 。volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的 。volatile仅能实现变量的修改可见性 , 并不能保证原子性;synchronized则可以保证变量的修改可见性和原子性 。volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞 。volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化 。
- 降低资源消耗 。通过重复利用已创建的线程降低线程创建和销毁造成的消耗 。
- 提高响应速度 。当任务到达时 , 任务可以不需要等到线程创建就能立即执行 。
- 提高线程的可管理性 。线程是稀缺资源 , 如果无限制的创建 , 不仅会消耗系统资源 , 还会降低系统的稳定性 , 使用线程池可以进行统一的分配 , 调优和监控 。
- 新建状态(NEW)当程序使用 new 关键字创建了一个线程之后 , 该线程就处于新建状态 , 此时仅由 JVM 为其分配内存 , 并初始化其成员变量的值 。
- 就绪状态(RUNNABLE)当线程对象调用了 start()方法之后 , 该线程处于就绪状态 。Java 虚拟机会为其创建方法调用栈和程序计数器 , 等待调度运行 。
- 运行状态(RUNNING)如果处于就绪状态的线程获得了 CPU , 开始执行 run()方法的线程执行体 , 则该线程处于运行状态 。
- 阻塞状态(BLOCKED)阻塞状态是指线程因为某种原因放弃了 cpu 使用权 , 也即让出了 cpu timeslice , 暂时停止运行 。直到线程进入可运行(runnable)状态 , 才 有机会再次获得 cpu timeslice 转到运行(running)状态 。阻塞的情况分三种等待阻塞(o.wait->等待对列) , 运行(running)的线程执行 o.wait()方法 , JVM 会把该线程放入等待队列(waitting queue)中 。同步阻塞(lock->锁池) , 运行(running)的线程在获取对象的同步锁时 , 若该同步锁被别的线程占用 , 则 JVM 会把该线程放入锁池(lock pool)中 。其他阻塞(sleep/join) , 运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法 , 或者发出了 I/O 请求时 , JVM 会把该线程置为阻塞状态 。当 sleep()状态 超时、 join()等待线程终止或者超时、或者 I/O处理完毕时 , 线程重新转入可运行(runnable)状态 。
推荐阅读
- 袁天罡的后人是谁 历史上有袁天罡这个人吗
- Mysql数据库实现主从同步,看这一篇就够了
- 10分钟自建企业级Docker镜像仓库!这个开源项目太顶了
- 电视机顶盒和网络机顶盒哪个好?
- Python自带爬虫库urllib使用大全
- 癫痫的前兆有哪些症状
- 如何治疗痔疮的小窍门
- 皮肤受损后该如何修复
- 西装|辣目洋子教你玩转西装穿搭,微胖女生这样穿也能在职场脱颖而出
- 老年人脚麻木吃什么药