java学习痛点难点就是多线程,同时很多公司面试时也要求精通多线程。为了克服这个难点,我写下学习多线程的所有遇到的值得记录的知识点。
先来一个线程测试类:
public class LiftOff implements Runnable {
private int countDown = 100;
private static int taskCount = 0;
private final int id = taskCount++;
public String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "lift off") + ")";
}
@Override
public void run() {
// TODO Auto-generated method stub
while (countDown-- > 0) {
System.out.println(status());
Thread.yield();
}
}
public static void main(String[] args) {
// 线程不安全的
// 线程执行方案一
// 客户端直接执行任务
// LiftOff l=new LiftOff();
// for(int i=0;i<5;i++){
// new Thread(l).start();
// }
// 线程执行方案二
// 使用jdk5之后的 Executor来管理和执行线程
ExecutorService service = Executors.newCachedThreadPool();// 命令设计模式
LiftOff l = new LiftOff();
for (int j = 0; j < 5; j++) {
service.execute(l);
}
service.shutdown();
//非常常见的情况是,单个Executor被用来创建和管理系统所有的任务
//对shutdown方法的调用可以防止新的任务被提交给executor,当前线程将继续运行再shutdown调用之前提交的任务,并且这个程序在executor中所有的任务运行结束之后尽快退出
//Executor允许管理异步线程的执行,无需显示管理线程的生命周期,Executor是javaSE5/6启动线程的优选方法。
}
}
CachedThreadPool、FixedThreadPool、SingleThreadExecutor 的区别
FixedThreadPool一次性预见性的线程分配,因此也限制了线程的数量。这个可以节省创建线程的开销
SingleThreadExecutor 线程数量为一的FixedThreadPool 如果想singleThreadExecutor中提供了多个任务。
这些任务会排队,所有任务使用同一个线程,singleThreadExecutor会序列化所有提交给他的任务,并维护在它的隐藏的悬挂任务队列
cachedThreadPool 在程序执行过程中,通常会创建与所需线程数量相同的线程数,然后在它回收旧线程时停止创建新的线程。因此它是合适的Executor的首先,只有当这种方式出现问题了,才需要切换到FixedThreadPool