核心类库阶段回顾
Array大小固定,ArrayList的大小是动态变化的。
ArrayList提供了更多的方法和特性:比如 :addAll(),removeAll(),iterator()等等。
对于基本数据类型,集合使用自动装箱来减少编码工作量。但是,当处理固定大小基本数据类型的时候,这种方式相对较慢。
而且ArrayList与Vector底层都是基于数组的,因此它们的实现代码也大致相似。区别在于Vector是一个古老的集合,从JDK1.0开始就有了,因此它包含了大量方法名很长的方法,JDK 1.2开始引入集合框架,引入List接口,才让Vector实现了List接口,因此又增加了一些List接口中定义的方法。总体来说,ArrayList可以完全代替Vector,除了在一些很古老的API中强制要求使用Vector之外。
Vector还有一个特征:它是线程安全的,因此性能比较差。而ArrayList并不是线程安全的,因此性能较好。实际上即使我们要在多线程环境下使用List集合,也应该选择ArrayList,而不是Vector,因为Java还提供了一个Collections工具类,它可以把ArrayList包装成线程安全的集合类,例如如下代码:
1 List list = Collections.synchronizedList(new ArrayList());
TreeMap是有序的,HashMap和HashTable是无序的。
Hashtable的方法是同步的,HashMap的方法不是同步的。这是两者最主要的区别。
这就意味着Hashtable是线程安全的,HashMap不是线程安全的。HashMap效率较高,Hashtable效率较低。 如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。
Hashtable不允许null值,HashMap允许null值(key和value都允许)
父类不同:Hashtable的父类是Dictionary,HashMap的父类是AbstractMap
Hashtable中hash数组默认大小是11,增加的方式是 old*2+1。
HashMap中hash数组的默认大小是16,而且一定是2的指数。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
1 public class MyThread extends Thread{ 2 public void run(){ 3 //run方法就是线程要执行任务的方法 4 //这是执行路径 触发方式不是调run而是用start()启动系统 5 for(int i=0;i<10;i++){ 6 System.out.printIn("m线程"+i); 7 } 8 } 9 }
Demo.java
1 public class Demo{ 2 //多线程技术 抢占 3 public static void main(String[] args){ 4 MyThread m=new MyThread(); 5 //启动m线程 6 m.start(); 7 for(int i=0;i<10;i++){ 8 System.out.printIn("main'线程"); 9 } 10 } 11 }
程序启动 > main线程开启 > main方法执行 > 创建m对象 >
1.m线程开启 循环十次
2.main本身循环十次
2.实现Runnable
用于给线程执行任务
MyRunnable.java
1 public class MyRunnable implements Runnable{ 2 //线程的任务 3 public void run(){ 4 for(int i=0;i<10;i++){ 5 System.out.prinIn("m线程"); 6 } 7 } 8 }
Demo.java
1 public class Demo{ 2 public static void main(String[] args){ 3 //1.实现Runnable 创建一个任务对象 4 MyRunnable r=new MyRunnable(); 5 //2.创建一个线程并分配任务 6 Thread t=new Thread(r); 7 //3.执行这个线程 8 t.start(); 9 for(int i=0;i<10;i++){ 10 System.out.printIn("主线程"); 11 } 12 } 13 }
执行顺序和上同
实现Runnable和继承Thread相比优势
- 通过创建任务给线程分配的方式,适合多线程同时执行情况。
- 避免单继承局限。
- 任务与线程分离提高程序健壮性。
- 线程池技术仅授权Runnable型任务,不接收Thread型。
- New(初始化状态)
- Runnable(可运行/运行状态)
- Blocked(阻塞状态)
- Waiting(无时间限制的等待状态)
- Timed_Waiting(有时间限制的等待状态)
- Terminated(终止状态)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~