1.1进程和线程的区别
1.进程和线程的由来
串行:初期计算机只能床行执行任务,并且需要长时间等待用户输入
批处理:预先将用户的指令集中成清单,批量创行处理用户指令,仍然无法并发执行。
进程:进程独占内存空间,保存各自运行状态,相互间不干扰且可以互相切换,为并发处理任务提供了可能
线程:共享进程的内存资源,相互间切换更快速,支持更细粒度的任务控制,使进程内的子任务得以并发执行。
进程是资源分配的最小单位,线城市CPU调度的最小单位
1.所有与进程相关的资源,都被记录在PCB中
2.进程是抢占处理机的调度单位,线程属于某个进程,共享其资源
3.线程只由堆栈寄存器,程序计数器和TCB(线程计数表)组成
总结:
1.线程不能看作独立应用。而进程可看作独立应用。
2.进程有独立的地址空间,相互不影响,线程只是进程的不同执行路径
3.线程没有独立的地址空间,多进程的程序比多线程的程序健壮。
4.进程的切换比线程的切换开销大。
JAVA进程和线程的关系:
1. Java对操作系统提供的功能进行封装,包括进程和线程
2.运行一个程序会产生一个进程,进程包含至少一个线程
3.每个进程对应一个JVM实例,多个线程共享JVM里的堆
4.Java采用单线程变成模型,程序会自动创建主线程
5.主线程可以创建子线程,原则上要后于子线程完成执行。
2.Thread中的start和run的区别:
1.调用start()方法会创建一个新的子线程并启动
2.run()方法只是Thread的一个普通方法的调用,还是在主线程里执行。
3.Thread和Runnable是什么关系:
Thread是一个类,而Runnable则是一个接口
1.Thread是实现了Runnable接口的类,使得run支持多线程
2.因类的单一继承原则,推荐多使用Runnable接口。
4.如何给run()方法传参:
1.构造函数传参
2.成员变量传参
3.回调函数传参
5.如何实现处理线程的返回值:
1.主线程等待法:即我们可以让主线程循环等待,直到目标子线程返回值为止。(缺点,参数一多,结构臃肿)
2.使用Thread类的join()阻塞当前线程以等待子线程处理完毕
3.通过Callble接口实现,通过FutureTask Or线程池获取
6.线程的状态:
1.新建(New):创建后尚未启动的线程状态
2.运行(Runnable):包含Running和Ready
3.无限期等待(Waiting):不会被分配CPU执行时间,需要显式被唤醒
4.限期等待(Timed Waiting):在一定时间后会由系统自动唤醒
5.阻塞(Blocked): 等待获取排它锁
6.结束(Terminated):已终止线程的状态,线程已经结束执行。
这三种方式会让我们线程进入无限期等待状态:
没有设置Timeout参数的Object.wait()方法
没有设置Timeout参数的Thread.join()方法
LockSupport.park()方法
以下几种方式会让线程进入限期等待状态:
Thread.sleep()方法。
设置了Timeout参数的Object.wait()方法
设置Timeout参数的Thread.join()方法
LoackSupport.parkNanos()方法
LoackSupport.aprkUnitil()方法
7.sleep和wait的基本差别:
slepp是Thread类的方法,wait是Object类中定义的方法
sleep()方法可以在任何地方使用
wait()方法只能在synchronized方法或synchronized块中使用
最主要的本质区别:
Thread.sleep只会让出CPU,不会导致锁行为的g改变
Object。wait不仅让出CPU,还会释放已经占有的同步资源锁
8.notify和notifyAll的区别:
锁池EntryList
等待池WaitSet
锁池:
假设线程A已经拥有了某个对象(不是类)的锁,而其他线程B、C想要调用这个对象的某个synchronized方法(或者块),由于BC线程在进入对象的synchronized方法(或者块)之前必须先获得该对象锁的拥有权,而恰巧该对象的锁目前正被线程A所占用,此时B C线程就会被阻塞,进入一个额地方去等待锁的释放,这个地方便是该对象的锁池
notifyAll:会让所有处于等待池的线程全部进入锁池去竞争获取锁的机会
notify:只会随机选取一个处于等待池中的线程进入锁池去竞争获取锁的机会
9.yield:
当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示。
10.如何中断线程
已经被抛弃的方法:
1.通过调用stop()来停止线程:这种方法太过暴力,当线程A调用B的stop()方法来停止B线程,但此时A是不知道B的执行 情况的,如果暴力停止,容易导致B线程的一些清理工作无法完成。还有一个情况是,执行B之后线程会马上释放锁,这 有可能引发数据不同步的问题。基于以上问题,stop被抛弃了
2.通过调用suspend()和resume()方法:类似还有这两个方法,也同样被废弃
目前使用的方法:
1.调用interrrupt(): 通知线程应该中断了,只是一种暗示,具体是中断还是执行,应该由被执行的线程自己去处理
如果线程处于被阻塞状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常
如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,被设置中断标志的线程将继续正常运行,不受影 响。
2.也就是说interrupt并不能真正的中断线程,需要线程自己配合才行:
在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,被设置中断标志的线程将继续正常运行,不受影 响。