创建线程的方式
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
- 使用线程池
sleep()和wait()的区别
- sleep()是Thread类的静态本地方法,而wait()是Object类的本地方法
- sleep()没有释放锁,wait()会释放锁
- sleep()重点在于暂停当前线程,wait()重点在于线程间的交互
- sleep()必须指定一个时间,时间到了后线程恢复运行,wait()可以选择指定时间,若不指定时间则需要其他线程使用notify()或notifyAll()唤醒
volatile关键字
在Java中将变量声明为volatile,表示此变量是多线程共享的,每次读取时都到主存中读取。
乐观锁和悲观锁
悲观锁总是假设最坏的情况,每次获取共享资源时先上锁,如果其他线程需要资源就会阻塞。例如Synchronized关键字和ReentrantLock独占锁。
乐观锁总是假设最好的情况,线程获取资源时不上锁,而是在提交修改的时候去验证对应的资源是否被其他线程修改了,例如CAS算法。
悲观锁适合于写操作较多,乐观锁适合于读操作较多。
线程池
创建方法
- 通过ThreadPoolExecutor构造函数传入参数创建
- 通过Executor框架的工具类Executors创建
线程池参数
1 | public ThreadPoolExecutor( |
拒绝策略
- ThreadPoolExecutor.AbortPolicy(默认):直接拒绝任务并抛出异常
- ThreadPoolExecutor.CallerRunsPolicy:调用自己的线程来执行任务
- ThreadPoolExecutor.CallerRunsPolicy:直接拒绝任务,不报异常
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃掉最早的未处理任务,把新的任务加入队列