早期单核CPU的情况下是没有真正的并发的,其实是并行,多线程之间争夺cpu时间片
如果主线程任务在子线程前面,会先跑主线程任务,其实就是Java解释语言机制顺序按行执行,子线程都没有启动,肯定不会执行子线程任务。
如果调用run方法,只会将其当成普通方法, 不会当成启动线程,也就不会出现执行顺序问题,会一直把各自线程的任务全部执行完。
Runnable接口实现类对象是任务target,要交给Thread
new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("又一个子线程"+i);
}
}).start();
使用lambda表达式简化启动子线程
使用FutureTask的get方法获取线程返回值。
找了个监工 看call方法,会等待call方法结束。
这样可以不用再用setName方法为线程命名。
如果先更新,就可能不会出现安全问题,因为先更新可能money就会变为0,另一个线程判断的结果就是余额不足。
对临界资源进行上锁
this指代当前对象的地址!对象的地址是在这个对象new出来之后才有的。所以可以作为一把不影响别人的锁
线程池
有三个任务,三个核心线程会每人分配一个, 再加入五个任务,会放进任务队列,再加一个任务,此时满足创建临时线程的要求,会创建一个新线程,再加入一个任务,继续再创建一个新线程,此时已经达到线程池最大容量,再加入一个任务,则不会创建线程,且任务队列也满了,会触发拒绝策略,抛出异常。
四个任务都会执行,只用三个核心线程,因为可以进行线程复用。
如果多个任务,前面任务没有结束,即使后面的任务到了该执行的时间也不会执行,因为只有一个线程;另外如果前面任务出现异常会导致线程死亡,后面任务的执行都会被影响。