关于线程
进程
程序一次执行过程,独立运行,如任务管理器里的(.exe)
线程
一个进程中可以有多个线程
线程共享进程的堆和方法区,独有程序计数器,虚拟机栈和本地方法栈
堆: 存放对象实例
方法区 :存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
//java比c++多封装了内存动态分配和垃圾回收技术(JVM)
程序计数器 :比作字节码行号指示器
私有原因:为了线程切换后能恢复到正确的执行位置。
虚拟机栈:局部变量表 为java方法服务
本地方法栈:为native方法服务
私有原因:保证线程中的局部变量不被别的线程访问到
//一个Native Method就是一个java调用非java代码的接口。
并发编程可能会遇到很多问题,比如:内存泄漏、上下文切换、死锁还有受限于硬件和软件的资源闲置
线程的生命周期
new 初始态 runnable 运行状态 blocked 阻塞 waiting 等待 time waiting 超时等待
termnated 终止状态

线程之间通信
(0) Thread
sleep()调用线程会暂时让出时间的执行权,这期间不参与cpu的调度,不让出锁
(1)Object的wait() / notify()方法
wait() 相当于让当前线程交出此对象的monitor,然后进入等待状态
notify()方法能够唤醒一个正在等待该对象的monitor的线程,必须在同步块或者同步方法中进行
nofityAll()方法能够唤醒所有正在等待该对象的monitor的线程
*唤醒不代表获取monitor
(2)Lock和Condition的await() / signal()方法
(3)BlockingQueue阻塞队列方法 未学习
生产者--消费者
public void run(){
while(true){
synchronized(缓冲区queue){
while(缓冲区满){
try{
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
queue.notify();//线程唤醒
}
}
queue.offer(i++);//队列满时 add()方法抛出unchecked异常,offer()法返回false
queue.notifyall();//线程唤醒
}
}
public Lock lock = new ReentrantLock();
public Condition condition = lock.newCondition();
public void run(){
while(true){
lock.lock();//获得锁
while(缓冲区满){
try{
condition.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
queue.offer(i++);
Condition.signalAll();//线程唤醒
lock.unlock();
}
}
线程的死锁
死锁的条件
互斥条件:该资源任意一个时刻只由一个线程占用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
简单案例: 线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。 解决 B监听A的整个流程 破坏了破坏循环等待条件