1 线程状态:
New 新生,Runnable 运行,Blocked 阻塞,waiting 等待(死等),TimedWaiting 超时等待(过期不候),Terminated 终止。
2 Wait 和Sleep 区别
Wait:来自object。释放锁。只有在同步代码块中使用。
Sleep:来自Thread。不释放锁。可在任意地方使用。
3 线程就是一个单独的资源类
4 synchronized 和Lock 区别
synchronized :内置关键字,无法获取锁状态,执行结束会自动释放锁,线程一死锁后线程二会一直等,可重入锁,不可中断,非公平,适合少量代码同步。
Lock :Java类,可获取锁状态,必须手动释放锁,不释放会死锁,线程一死锁后线程二不一定等待,可重入锁,可判断锁,非公平可自己控制。适合锁大量代码块。
5 线程间通信问题:实际就是等待唤醒问题,如生产者消费者问题
6 线程可以被唤醒且不被通知,就是虚假唤醒,解决方式是不要用if 要使用While。等待应该总是出现在循环中,防止虚假唤醒。
7 Condition 线程监视器,用await(),signalAll()取代synchronized的wait(),notifyAll()。可实现唤醒指定线程。
8 注意分析锁的是对象(锁方法的调用者)还是class类。是否同一把锁。静态方法锁的类是同一把锁。
9 ArrayList 线程不安全,可使用CopyOnWriteArrayList()。写入时复制。写入时先复制然后写入之后再解锁插回。同理CopyOnWriteSet()。HashMap,LinkedQueue对应的安全工具为ConcurrentHashMap,ConcurrentLinkedQueue
10 Callable类似于Runnable,可以有返回值(结果又缓存),可抛出异常。使用FutureTask 适配器启动线程。
11 CountDownLatch 减法计数器,有初始线程大小,内置自减1,等待计数器归零(wait)方法,归零后执行特定内容。
12 CyclicBarrier 加法计数器,有初始线程大小,执行后会自动加一,达到初始大小后执行特定内容。
13 Semaphore 信号量,有初始线程大小,有acquire()得到,release()释放,当有多个线程(超过初始线程大小)操作时,仅允许初始线程大小的线程执行acquire后的逻辑,要等到release后才会有新的线程进入,用于限流。
14 ReadWriteLock 读写锁new ReentrantReadWriteLock(),写入时只能一个线程写入writeLock().lock(),读取时可以多个一起读。
15
BlockingQueue阻塞队列,类比list。先进先出,队列满阻塞进入,空的阻塞取出。
操作 | 抛出异常 | 有返回值,不抛异常 | 阻塞等待 | 阻塞超时等待 |
添加 | add(“”) | offer(“”) | put(“”) | offer(“”)有超时参数 |
移除 | remove() | poll() | take() | poll()有超时参数 |
判断队首 | element() | peek() |
16 synchronizedQueue 同步队列,只有一个元素,一个线程放入一个元素后必须被取出才能再次放入。
17
线程池,三大方法,七大参数。
Executors.newCachedThreadPool();//可伸缩大小线程池(和CPU有关)
Executors.newFixedThreadPool(4);//固定大小线程池
Executors.newSingleThreadExecutor();//单例,单个线程
//int corePoolSize,//核心线程数,一直启动
//int maximumPoolSize,//最大核心线程池大小
//long keepAliveTime,//超时没有调用就会释放,核心线程外的线程未被使用
//TimeUnit unit,//超时单位
//BlockingQueue<Runnable> workQueue,//阻塞队列
//ThreadFactory threadFactory,//线程工厂
//RejectedExecutionHandler handler//拒绝策略
AbortPolicy不处理抛出异常 CallerRunsPolicy 哪来的回哪去DiscardPolicy 丢掉任务不抛异常 DiscardOldestPolicy 尝试与第一个抢,不抛异常
ThreadPoolExecutor poll=new ThreadPoolExecutor(
2,
5,
5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
18 断定型接口 Predicate 一个传入参数,返回布尔值。
19 函数型接口 Function 一个输入参数,一个输出参数。
20 消费型接口 Consumer 只有一个输入,没有输出。
21 供给型接口 Supplier 没有参数,只有一个返回值。
22 以上配合Stream 流计算。
23 ForkJoin 拆分任务,工作窃取,双端队列。
24 CompletableFuture 异步回调
25 Volatile 轻量级同步机制,内置关键字。
保证可见性:多个线程操作主存变量,可见到变量改变。
不保证原子性:在不使用synchronize 和lock时只有使用原子操作(原子类)
禁止指令重排 (程序并不一定按照代码顺序执行)通过加内存屏障
26
1:lock: 把主内存变量标识为一条线程独占,此时不允许其他线程对此变量进行读写。
2:unlock:解锁一个主内存变量。
3:read:把一个主内存变量值读入到线程的工作内存,强调的是读入这个过程。
4:load:把read到变量值保存到线程工作内存中作为变量副本,强调的是读入的值的保存过程。
5:use:线程执行期间,把工作内存中的变量值传给字节码执行引擎。
6:assign(赋值):字节码 执行引擎把运算结果传回工作内存,赋值给工作内存中的结果变量。
7:store: 把工作内存中的变量值传送到主内存,强调传送的过程。
8:write: 把store传送进来的变量值写入主内存的变量中,强调保存的过程。
27 饿汉式单例,开始就加载类内存 静态方式构造。不存在线程安全问题。
28 懒汉式单例,只提供实例,不创建对象,使用到时才加载 不为空才构造,要对构造方法加synchronize保证安全,降低效率。
29 DCL 懒汉式,双重检测锁模式 先检测为空后 再对类加锁创建,然后在检测为空后才创建实例。因为创建实例不是原子性操作,所以需要对实例加volatile。
30 Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息。
31 原子操作 CAS compareAndSwap 达到期望更新否则不更新. ABA问题。因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。
32 可重入锁 拿到一把锁后还可以获取锁,拿到外部锁的时候会自动获取该锁内的其他锁。注意使用Lock 时解锁要与加锁对应使用,不可省去。
33 自旋锁:是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
34 排查死锁
jps –l 查看当前所有进程信息
jstack XXXX 通过进程号找到死锁
35
- 悲观锁 比较悲观的锁,总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。
- 乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量