1、线程和进程的区别:
进程:程序由指令和数据组成,指令想要运行,数据想要读写,就必须将指令加载到cpu,
数据加载到内存。在指令运行过程中还需要用到磁盘,网络等设备。进程就是用来加载指令 管理内存 管理io的。进程可以看作时程序的一个实例,大部分的程序可以同时运行多个实例进程,也有的程序只能启动一个实例进程
线程:一个进程可以分为多个线程。一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给cpu执行。
2、并发和并行的区别:
并发:把任务在不同的时间点交给处理器进行处理 同一时间 任务依次运行
并行:把每个任务分配给每一个处理器独立完成 同一时间 任务一定是同时运行
并发不是并行 并行是让不同的代码片段同时在不同的物理处理器上执行 并行的关键是同时做跟多事情 而并发是值同时管理跟多事情 这些事情可能只做了一半就被暂停去做别的事情了
在很多情况下 并发的效果比并行好,因为操作系统和硬件的总资源一般很少 但能支持系统封同时做很多的事情
3、线程的四种创建方式:
- 直接使用Thread
- 使用Runnable配合Thread
- FutureTask配合Thread
- 线程池
4、线程有那些状态:
- 新建 new Thread
- 可运行状态RUNABLE 调用start方法
- 终结状态 run方法中代码执行完毕
- 阻塞状态 没有获取锁的线程 当获取锁的线程释放掉锁 重新抢占锁成功----》可运行状态
- 等待状态 获取锁的线程 调用锁对象 .wait方法
- 有时限的等待 获取锁的线程 调用锁对象 .wait(long)方法 调用线程的sleep方法
5、为什么要使用线程池?
- 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务
- 可以根据系统的承受能力,调整线程池中工作线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程大约1MB内存,线程开的越多 消耗的内存也就越大,最后死机)
6、线程池的构造方法里几个参数的作用分别是什么?
corePoolSize核心线程数
maximumPoolSize最大线程数
keepAliveTime 生存时间
unit 时间单位
workQueue 工作队列
threadFactory线程工厂
handler拒绝策略
7、线程池流程:
1、当我们向线程池中添加任务 有核心线程执行任务 如果核心线程都在执行任务,将任务假如到任务队列,等待核心线程执行完任务,从队列中获取任务执行,如果队列已经满了 创建救济线程,有急救线程执行任务,急救线程执行完任务后,如果在keepAliveTime时间内没有任务执行,销毁,如果救济线程也无法创建 则触发拒绝策略
8、线程池拒绝策略有哪些:
抛异常
由调用者执行任务
丢弃任务
丢弃最早排队的任务,把新任务添加到工作队列
9、notify()和notifyAll()有什么区别:
notify 唤醒锁对象等待区随机一个线程
notifyAll 唤醒锁对象等待区所有的线程
10、wait和sleep的区别:
相同点:wait() ,wait(long) 和 sleep(long) 的效果都是让当前线程暂时放弃 CPU 的使用权,进入WAITING Time_Waiting 状态
不同点:
1、方法归属不同 sleep是thread的静态方法 而wait是Object的成员方法 每个对象都有
2、醒来时机不同 执行sleep和wait的线程都会在等待相应毫秒后醒来 wait 还可以被notify唤醒 wait如果不唤醒就一致等待下去;他们都可以被打断唤醒
3、锁特性不同 wait方法必须基于锁对象调用 直接调用报错,而sleep没有限制,wait方法执行后会释放对象锁,允许其他线程获得该对象锁,sleep如果在synchronized代码块中执行,并不会释放对象锁
11、lock锁和synchronized锁区别:
语法局面 synchronized是关键字 底层是通过c++代码实现锁 synchronized同步代码块执行完毕会自动释放锁 lock是一个接口 用java语言实现 需要手动调用unlock方法释放锁
功能层面:具备基本的互斥 同步 锁重入功能 ——互斥 同步 重入
Lock 提供了许多 synchronized 不具备的功能 Condition condition=lock.newCondition();
可以利用条件变量进行await 将线程假如等待队列
可以利用条件变量进行condition.signalAll();唤醒等待队列某个线程
Lock有适合不同场景的实现
12、悲观锁和乐观锁的区别:
悲观锁的核心代码是synchronized lock
思想:只有获取锁的线程才能操作共享变量,每次只有一个线程能获取锁成功,获取锁失败的线程都要进入阻塞队列等待
线程从可运行到阻塞 再从阻塞到可运行,涉及到上下文切换,如果频繁发生会影响效率
synchronized和lock在获取锁的时候,如果锁已经被其他线程占用,还会充实几次
乐观锁 乐观锁的代表是Atomiclnteger,使用后cas保证原子性
思想:每次只有一个线程能修改成功共享变量,其他i需改失败的线程不需要阻塞,不断重试,知道成功;由于所有的线程一致运行,不需要阻塞,不牵涉频繁上下问切换 需要多喝cpu的支持cpu大于线程数量