大纲
概览
进程与线程
java线程
常见方法
start和run
run
start
小结
- 直接调用 run 是在主线程中执行了 run,没有启动新的线程
- 使用 start 是启动新的线程,通过新的线程间接执行 run 中的代码
sleep 与 yield
限制对cpu的使用
sleep
- 此处利用linux,分配了一核cpu,直接while(true)才可以模拟出100%
- 多核的话,模拟不出来
- 加上sleep,cpu占用从100%降低到5%,效果明显;
join
为什么需要join
应用之同步
以调用方角度来讲,如果
- 需要等待结果返回,才能继续运行就是同步
- 不需要等待结果返回,就能继续运行就是异步
等待多个线程结果
有时效的 join
- 如果join(2s),线程只需要1s执行完,则主线程1s后继续执行
- 如果join(2s),线程需要3s执行完,则主线程最多等到2s后继续执行
interrupt
打断 sleep,wait,join 的线程
这几个方法都会让线程进入阻塞状态 打断 sleep 的线程, 会清空打断状态,以 sleep 为例
打断正常运行的线程
模式之两阶段终止
错误思路
两阶段终止
打断 park
不推荐使用的方法
守护线程
五种状态
操作系统层面出发
六种状态
这是从 Java API 层面来描述的
根据 Thread.State 枚举,分为六种状态
代码
@Slf4j(topic = "c.TestState")
public class TestState {
public static void main(String[] args) throws IOException {
Thread t1 = new Thread("t1") {
@Override
public void run() {
log.debug("running...");
}
};
Thread t2 = new Thread("t2") {
@Override
public void run() {
while(true) { // runnable
}
}
};
t2.start();
Thread t3 = new Thread("t3") {
@Override
public void run() {
log.debug("running...");
}
};
t3.start();
Thread t4 = new Thread("t4") {
@Override
public void run() {
synchronized (TestState.class) {
try {
Thread.sleep(1000000); // timed_waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t4.start();
Thread t5 = new Thread("t5") {
@Override
public void run() {
try {
t2.join(); // waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t5.start();
Thread t6 = new Thread("t6") {
@Override
public void run() {
synchronized (TestState.class) { // blocked
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t6.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// new
log.debug("t1 state {}", t1.getState());
// runnable
log.debug("t2 state {}", t2.getState());
// TERMINATED
log.debug("t3 state {}", t3.getState());
// TIMED_WAITING
log.debug("t4 state {}", t4.getState());
// WAITING
log.debug("t5 state {}", t5.getState());
// BLOCKED
log.debug("t6 state {}", t6.getState());
System.in.read();
}
}
结果:
17:30:07.220 c.TestState [t3] - running...
17:30:07.723 c.TestState [main] - t1 state NEW
17:30:07.725 c.TestState [main] - t2 state RUNNABLE
17:30:07.725 c.TestState [main] - t3 state TERMINATED
17:30:07.725 c.TestState [main] - t4 state TIMED_WAITING
17:30:07.725 c.TestState [main] - t5 state WAITING
17:30:07.725 c.TestState [main] - t6 state BLOCKED
总结
应用之统筹(烧水泡茶)
join
@Slf4j(topic = "c.Test16")
public class Test16 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
log.debug("洗水壶");
sleep(1);
log.debug("烧开水");
sleep(5);
},"老王");
Thread t2 = new Thread(() -> {
log.debug("洗茶壶");
sleep(1);
log.debug("洗茶杯");
sleep(2);
log.debug("拿茶叶");
sleep(1);
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("泡茶");
},"小王");
t1.start();
t2.start();
}
}
结果:
17:48:20.594 c.Test16 [老王] - 洗水壶
17:48:20.594 c.Test16 [小王] - 洗茶壶
17:48:21.602 c.Test16 [小王] - 洗茶杯
17:48:21.602 c.Test16 [老王] - 烧开水
17:48:23.607 c.Test16 [小王] - 拿茶叶
17:48:26.607 c.Test16 [小王] - 泡茶
Process finished with exit code 0
共享模型之管程
并发之共享模型
管程-悲观锁(阻塞)
JMM
无锁-乐观锁(非阻塞)
不可变
本章内容
- 不可变类使用
- 不可变类设计
- 无状态类设计
日期转化的问题
同步加锁
不可变类