线程
#创建线程的方式
- 方法一
extends Thread
- 方法二
implements Runnable
- 方法三
implements Callable<T>
-
方法三
线程池
Executors.newFixedThreadPool();
Executors.newSingleThreadExecutor();
Executors.newCachedThreadPool();
Executors.newScheduledThreadPool();
一般需要手动创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler)
参数说明
-
coolPoolSize
核心线程数当前线程池中空闲的线程数, 运行时该线程始终不会被销毁, 要小于
maximumCoreSize
-
maximumCoreSize
线程池能创建的最大线程, 当
WorkQueue
的队列存储的任务满了, 且当前正在运行的线程数小于
maximumCorseSize
时, 就会创建一个线程来运行不在WorkQueue
中的任务, 一般设置为一般设置为比
Runtime.getRuntime().availableProcessors()
大1或2 -
keepAliveTime
如果当前线程数大于
corePoolSize
时且有线程空闲时间大于keepAliveTime
时, 销毁线程数至corePoolSize
-
unit
keepAliveTime
的时间单位 -
workQueue
阻塞队列一般采用
LinkedBlockingQueue
, 默认是无边界的, 必须要指定大小 -
threadFactory
用于自定义线程的名字
-
handler
拒绝策略, 当当正在运行的线程等于
maximumPoolSize
且大于workQueue
队列满了,就会采取handler
-
new ThreadPoolExecutor.AbortPolicy()
线程池默认采用该模式handler
如果任务数超出队列与最大线程数的值时抛出异常
-
new ThreadPoolExecutor.DiscardPolicy()
抛弃溢出的任务
-
new ThreadPoolExecutor.DiscardOldestPolicy()
线程满了且超过阻塞队列容乃,移除队列头,将新任务放入队列末尾
-
#线程的状态
NEW
, RUNNABLE
, BLOCKED
, WAITING
, TIMED_WAITING
, TERMINATED
#sleep()与 wait()的区别
sleep()
报锁睡眠, wait()
阻塞时释放锁
#Synchronize
重锁/ 同步锁/ 悲观锁/ 互斥锁
-
一个线程调用了锁方法后,其他线程不能进入该类访问任一一个锁方法
-
访问的对象不是同一个,不会阻塞
-
访问对象非同步方法,不会阻塞
-
访问锁的类型不同,不会阻塞
#终止线程的方式
-
semaphore
信号量,标志位 -
stop()
过时, 有可能造成死锁 -
interrupt()
, 通过isInterrupted()
判断
#volatile
-
可见性
保证了当数据重新写回主存时数据,所有线程可见
-
有序性 (写在读之前)
对一个volatile域的写,happens-before于后续对这个volatile域的读
-
原子性 !!!注意volatile不具有原子性
保证操作不分隔
例如:
i++ 不具备原子性
分为三步
-
从主存中读取i
-
i+1
-
将数据写回主存
所以操作++时要上锁或是使用
Atomic
相关类, 凡是读写操作都不具有原子性 -
#ThreadLocal
每个线程中都有一个自己的 ThreadLocalMap 类对象,可以将线程自己的对象保持到其中,
各管各的,线程可以正确的访问到自己的对象。