Java面试题总结
1,线程中,并行和并发的区别
这两都是描述处理多个任务的方式
并发:某个时间段内处理多个任务的思想,这些任务不是真正的同一时刻的任务执行,而是通过cpu的快速切换,使得宏观(逻辑上)看起来是同时执行的。
如:单核处理器,在不同的时间片上轮流执行多个程序。
并发的目的是提高系统的响应效率和cpu资源的利用率。
并行:同一时刻,多条指令在多核cpu上同时执行,属于真正的物理上的同时。
2,cookie和session的区别
cookie:
数据由服务器端生成通过HTTP协议发送给客户端浏览器,存储在浏览器端,并在每次发送请求时自动携带该cookie,让服务器读取其中的信息。
特点:
存储量小:cookie大小通常受到浏览器的限制,一般不超过4KB,
客户端每次发送请求时,会自动附带cookie数据。
不安全:cookie中的数据可以被用户或其他网站访问到,不适合存储敏感信息。
方便JavaScript交换数据
方便获取用户信息
浏览器可能会禁用cookie。
使用场景:使用cookie来标识用户会话,实现用户的登录状态管理。
seesion
数据存储在服务器端,在客户端浏览器中仅保存一个与session相关的标识(session ID)
相对于cookie来说session的存储容量更大,无限制。
安全性高:session的数据存在服务器端,客户端不可见,因此适合存储敏感信息
应用场景:用户身份认证,存储用户信息,实现身份认证和权限管理。
区别:
存储位置:Cookie存储在客户端浏览器,Session存储在服务器端。
数据容量:Cookie的容量较小,一般不超过4KB;而Session可以存储更多的数据。
安全性:由于Cookie存储在客户端,其中的数据可被用户和其他网站访问,因此安全性较低;而Session数据存储在服务器端,对客户端不可见,因此相对较安全。
传输方式:Cookie通过HTTP协议自动发送给服务器,每次请求都会携带Cookie数据;而Session可以通过Cookie或URL重写的方式传递Session ID。
生命周期:Cookie可以通过设置过期时间来指定存储的时间,可以是短期的或长期的;而Session默认情况下会持续到用户关闭浏览器或会话超时。
应用场景:Cookie适合存储少量的数据,常用于用户身份认证、记住登录状态等场景;Session适合存储较大的数据,常用于购物车功能、跨页面数据传递等场景。
3,String和StringBuffer和StringBuilder的区别
String : 是不可变对象,每次对类型进行改变时,会生成一个新的String对象,然后将指针指向新的String对象。
安全性:StringBuffer
是多线程安全的,JDK1.0出现,方法都被同步了(被synchronized
修饰)保证了数据的一致性和完整性。由于要获取锁,性能上有一定损耗。
StringBuilder 多线程不安全 ,JDK5.0出现,是一个可变的字符序列
使用策略:
基本原则:操作少量数据用String;单线程操作大量数据,用StringBuilder;多线程操作大量数据,用StringBuffer。
多线程共享变量且需要保证结果的情况下用StringBuffer。其他情况使用StringBuider。
4,Sleep函数中的特殊用法sleep(0)
sleep函数被用来使程序暂停执行一段时间,这段时间可以是毫秒,秒等,这个函数的调用通常是为了避免程序执行过快或等待任务完成。
sleep(0):目的不是为了让程序真正休眠,而是为了让当前线程放弃时间片,让其他等待的任务有机会执行,在多线程,多任务环境可以提高程序效率。(避免线程饥饿,提示调度器给其他线程一个机会)
sleep(1):短暂休眠后又再次参与CPU的竞争。是为了在执行之间添加短暂延迟的场景或等待异步操作完成的
使用场景:
降低cpu使用率,如果有一个线程在忙等待(busy-waiting)某件事情的发生时,可在循环体中插入sleep(1)来减少此循环对cpu资源的占用
定时任务:在简单定时任务或需要延迟操作时,不需要精确的定时控制,可实现短暂延迟。
5,sleep()和yield() 方法的不同之处:
sleep会让线程处于阻塞状态,需要设置参数。
yield是直接让此线程再次进入可运行状态,参与与其他同优先级的线程的cpu资源竞争,不需要设置参数,此方法属于提示性方法,无强制性。
主要差异
意图上的不同:sleep(0) 更像是对调度器的一个“试探”,看是否有可能让出CPU时间;而 yield() 则明确地表达了一个意愿,即当前线程愿意让出自己的执行时间给其他线程。
行为的确定性:由于 sleep(0) 在很多实现中并不会真正导致线程让出CPU,其行为不如 yield() 明确。实际上,yield() 提供了一种比 sleep(0) 更清晰的方式来表达你希望线程让步的愿望,尽管这种愿望并不总是能得到满足。
适用场景:对于大多数应用场景来说,直接控制线程调度并不是推荐的做法,更好的方式可能是通过合理的线程池配置、任务划分以及同步机制来管理并发。因此,除非是在进行非常精细的性能调优或者了解具体的调度行为对应用有直接影响的情况下,一般不会频繁使用 sleep(0) 或 yield()。