Java 并发基础
一、进程与线程
程序:一段静态的代码,一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体,是应用软件执行的蓝本
进程: 是程序的一次动态执行,对应着从代码的加载、执行、结束的完整过程,是有生命周期的。
- 进程包括就绪状态、执行状态、阻塞状态
线程:线程是进程的一个实体、是CPU 调度和分派的基本单位,是比进程更小的能独立允许的基本单位
1.创建并启动一个线程
new Thread().start();
2.重写run 方法并创新一个线程
Runnable runnable = ()->{System.out.println("重写 run ...");};
new Thread(runnable).start();
3.线程组
- main 线程的ThreadGroup 称为 main
- 构造一个线程时候如果没有显示指定 ThreadGroup ,那么它将会和父线程一个Group
- ThreadGroup 不能管理Thread,可以对Thread 组织
4.进程内存与线程数量
进程内存 =堆内存 + 线程数量 * 栈内存
5.守护线程
一类特殊的线程,也称后台线程(如垃圾回收线程)。通过 setdAEMON 方法可以设置线程为守护线程
- 设置线程为守护线程必须再在线程启动之前,否则会报错
- 守护线程能够自动结束生命周期
二、线程 API
1.sleep()
可以指定线程的休眠时间,在 jdk1.5 之后 TimeUnit 替代Thread.sleep()
2.yield()
调用会提示调度器当前线程愿意放弃当前 cpu 资源,如果cpu 资源足够,则会忽略
3.setPriority()
设置线程的优先级(1~10),会产生弊端,空闲占用资源
4.join()
与 sleep 方法一样,是可中断的方法。会使当前宣布从永远的等待下去,直到被中断或者join 的线程执行结束
5.wait()
- wait 方法必须拥有当前对象的 monitor ,在同步块中使用
- 一旦执行wait,则放弃该对象的 monitor,其他线程继续抢占
- 是可断的方法
- 与sleep 的区别
- sleep 不会放弃 monitor ,wait 放弃
- sleep 属于线程特意的方法,wait 属于 Object 方法
- 都是可中断方法,都会使得线程进入阻塞状态
- sleep 阻塞后自动恢复,wait 需要 notify / notifyAl
6.notify / notifyAll
object 的方法
三、线程安全
synchronized 关键字
- synchronized 是一种排他机制,同一时间只能有一个线程执行操作
- 包括了 monitor enter 和 monitor exit 两个 jvm 指令
- 严格遵守 happens-before , 一个 monitor exit 之前一定有一个 monitor enter
- 如果 monitor 的计数器 为0 ,意味着 monitor 的锁还未被获得,如果获得则 +1
- 如果已经拥有monitor 的锁,重新获取,则再次 +1 ,monitor exit 则计数器 -1
四、发生死锁
- 交叉锁
- 内存不足
- 一问一答
- 数据库锁
- 文件锁
- 死循环