一、创建线程的几种方式
- 继承Thread类重写run方法
public static class MyThread extends Thread{
@Override
public void run(){
}
}
- 实现Runable接口
public static class RunnableTask implements Runnable{
@Override
public void run() {
}
}
RunableTask task =new RunableTιsk;
new Thread(task) .start() ;
new Thread(task) .start() ;
- 使用furureTask实现
//创建任务类
public static class CallerTask implements Callable<String>{
private String ss;
@Override
public String call() throws Exception {
if(Objects.isNull(ss)){
return ss;
}
return "jj";
}
}
FutureTask<String> stringFutureTask = new FutureTask<>(new CallerTask());
new Thread(stringFutureTask).run();
二、线程的通知与等待
-
wait()
当前线程必须有此对象的监视器,线程释放此监视器的所有权,必须等待其他线程唤醒或者经过指定时间可以继续争夺监视器所有权 -
sleep()
使当前线程进入睡眠状态,(放弃CPU使用权)使当前线程不会丢失监视器的所有权 -
notify()
唤醒此对象监视器上等待的单个线程 -
notifuAll()
唤醒此对象监视器上等待的所有线程 -
join()
Thread的方法,当前线程等待指定线程执行完毕
内部调用wait()方法等待(如何唤醒当前线程https://blog.csdn.net/shangguoli/article/details/108453551) -
yield()
Thread 的方法,让出CPU使用权
注:获取共享变量监视器的两种方法
执行行 synchronized同步代码块时,使用该共享变量作为参数
synchronized((共享变量){
}
调用该共享变量的方法,并且该方法使用synchronized修饰
synchronized void add(int i){
i++;
}
三、线程死锁
线程死锁指多个线程因争夺资源而互相等待的现象
避免线程死锁要注意获取资源的有序性和资源的释放
四、守护线程和用户线程
守护线程和用户线程的区别:当所有非守护线程结束时,jvm将退出
垃圾回收器等线程是守护线程
创建守护线程的方式daemon设置为true
- ThreadLocal
ThreadLocal提供线程本地变量(其实变量不共用)
五、多线程操作
多线程共享变量工作内存模型:线程获取共享变量时从主内存复制到私有内存,操作结束后将私有内存变量同步到主内存中
volatile关键字:保证内存的可见性,但不保证操作的原始性;用volatile关键字修饰的共享变量在执行写操作时不会复制到私有内存,而是把值直接刷新回主线程;
一、Java的原子性操作
synchronized能保证操作的原子性和对象内存的可见性。是独占锁,在进行读操作时会影响性能。
二、Java的CAS操作
CAS compareAndSwap比较并交换
四个操作:对象内存位置,对象中的变量偏移量,变量预期值和新的值
ABA问题:(环形转换问题)AtomicStampedReference 类给变量增加时间戳解决ABA问题
unsafe类提供一系列对象与偏移量的一些操作
三、悲观锁,乐观锁
悲观锁:排他锁,独占锁
乐观锁:共享锁
可重入锁:(synchronized)锁内部维护当前线程标识和关联一个计数器,当判定不是当前线程不允许获取锁,当该锁由当前线程占用时,计数器会累计加一,释放锁时会减一,直到0唤醒其他线程。
六、List的操作
- List家族中唯一一个保持数据安全性的集合CopyOnWriteArrayList
1、add操作时使用ReetractLock独占锁
2、通过复制原数组快照进行操作,完成后合并赋值
存在问题:
写时复制的弱一致性:对数组写和读取操作使用的并不是同一个对象。
//大致过程
CopyOnWriteArrayList cowList = new CopyOnWriteArrayList ();
Object[] elements = getArray();
Object[] newElements = Arrays.copyOf(elements, len + 1);
//修改操作使用的是newElements 对象;遍历操作使用的是elements 源对象
七、线程池的四大拒绝策略
线程池发生拒绝策略前提:当线程池核心线程都在使用中-任务数量大于线程池最大数量+队列数量时-----max;
1、CallerRunsPolicy 当任务达到max时,当前提交任务线程执行该任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
2、(默认策略)AbortPolicy 当任务达到max时直接抛出异常
/**
* A handler for rejected tasks that throws a
* {@code RejectedExecutionException}.
*/
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
3、DiscardPolicy 当任务达到max时 静默任务丢失
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
4、DiscardOldestPolicy 当任务达到max时 丢弃最早任务并执行当前任务
/**
* A handler for rejected tasks that discards the oldest unhandled
* request and then retries {@code execute}, unless the executor
* is shut down, in which case the task is discarded.
*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
八、线程池队列任务入队、取出操作
一、入队(当队列长度限制时)
1、add-添加在队尾-抛出异常IllegalStateException
2、offer-添加在队尾-返回false
3、put-等待空间-添加到队尾