源码:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(); }核心线程数和最大线程数一样,稳定高负荷工作,因此没用超出核心线程数回收的情况keepAliveTime 设置为0,等待队列用LinkedBlockingQueue无界队列
newSingleThreadExecutor 用于串行执行任务的场景,每个任务必须按顺序执行,不需要并发执行
源码:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
解释:
类似于newFixedThreadPool,只是顾名思义池中只有一个线程干活,相当于串行
newCachedThreadPool 用于并发执行大量短期的小任务,或者是负载较轻的服务器
源码:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
解释:
没用核心线程,最大线程数无限,线程60秒没任务干就停止 ,等待队列用直接握手队列SynchronousQueue,任务直接交给线程执行不会保存
newScheduledThreadPool 用于需要多个后台线程执行周期任务,同时需要限制线程数量的场景
源码:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); } private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
解释:
ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,使用优先级队列DelayedWorkQueue,运行时间短的任务先执行,否则先等待的先执行
newSingleThreadScheduledExecutor 用于需要后台单线程执行周期任务
解释:
单线程执行版的newScheduledThreadPool ,保证任务串行执行,保证串行返回
synchronized关键字
作用:
同步
可见性
使用方式
获取对象锁
同步代码块: 指定加锁对象,对给定对象加锁
synchronized(this){}
同步非静态方法: 作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁
public synchronized void methodA(){}
获取类锁
同步代码块: 指定加锁的类,对给定类加锁
synchronized(类名.class){}
同步静态方法: 作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁
public synchronized static void methodA(){}
实现方式
同步代码块:使用了monitorenter和monitorexit指令
同步方法:通过方法修饰符上的ACC_AYNCHRONIZED实现
monitorexit结束时会把更新直接刷入主内存
JVM中锁升级流程
volatile关键字作用:
保证数据线程可见性
避免指令重排
实现:
在字节码中加入了 lock 指令:
锁总线,其它CPU对内存的读写请求都会被阻塞,直到锁释放,不过实际后来的处理器都采用锁缓存替代锁总线,因为锁总线的开销比较大,锁总线期间其他CPU没法访问内存,通过缓存一致性协议确保拿到缓存值是最新的
lock后的写操作会把已修改的数据写回内存,同时让其它线程相关缓存行失效,从而重新从主存中加载最新的数据
不是内存屏障却能完成类似内存屏障的功能,阻止屏障两边的指令重排序
如何终止线程stop方法(别用)
立刻终止线程,过于粗鲁
清理工作可能完成不了
会立即释放锁,有可能引起线程不同步
interrupt方法
阻塞状态下会推出阻塞状态,抛出InterruptedException;运行状态下设置中断标志位为true,继续运行,线程自行检查标志位主动终止,相对温柔
线程如何通信线程的通信是指线程之间以何种机制来交换信息,在编程中,线程之间的通信机制有两种,共享内存和消息传递