1 基础知识
线程创建关键的三种方式。
实现runnaable的run方法
继承thread类并重写run 方法
使用futuretask方式(callable)
好处:
继承的好处是方便传参,set或者构造。
runnable只能使用主线程的final变量
java不支持多继承,如果继承了thread,就不能继承其他类。
futuretask可以拿到返回结果。
wait
wait调用前要获取对象的监视器锁,synchronized(共享变量),或者调用它的方法加synchronized修饰
调用wait只会释放当前共享对象的锁,其他的监视器锁不会释放。
notify
被唤醒的线程不能马上从wait方法返回执行,需要获取监视器锁之后才可以返回,这个就涉及到一个竞争过程,
notifyall只能唤醒调用这个方法前的线程。
sleep
让出CPU不让出锁,返回后直接就绪状态准备竞争CPU。
yield
让出CPU使用权,直接就绪状态,线程调度器会从就绪队列里获取一个优先级最高的,也可能是更改让出的那个。
sleep线程会阻塞挂起指定的时间,yield方法线程只是让出自己剩余的时间片,仍然处于就绪状态。
线程中断
线程协作的方法。
B可以调用A的interrupt方法设置A的中断标志位true。
线程上下文切换的时机:时间片用完,被其他线程中断。
破坏死锁的条件只能破坏请求保持和循环等待。
守护线程和用户线程
守护线程不影响JVM退出,main线程运行结束后JVM会创建一个destroyjavaVM的线程等待所有用户线程终止后终止JVM进程。
ThreadLocal
每个线程内部有一个名为threadLocals的成员变量hashmap。线程的本地变量存在这里。
如果线程不消亡,本地变量一直存在可能造成内存溢出,所以使用完毕要remove。
inheritableThreadLocal
为了解决子线程不能获取父线程的变量的问题产生的。
2 基础知识2
共享变量问题
线程有自己的私有内存,对应实际情况多CPU多个cache的情况,副本可能不一致。
所以并发情况下必要时要通过让缓存失效,线程只能去主存读取一致的信息。
synchronized
同步锁,内部锁(监视器锁)
排他锁
内存语义:synchronized块内变量从工作内存删除&#x