线程安全:线程安全就是多个线程同时操作同一个对象时,数据永远准确的情况
线程不安全:多个线程同时操作同一个对象时,存在数据不准确的情况,这就是线程不安全
如何解决线程不安全?
加锁!
synchroniazed的使用可以解决数据不准确的问题,synchronized就是锁,针对多线程进行线程安全的控制
所具备的特点:互斥:相互排斥。重入:重复进入,同一个线程可以重复的抢得该锁
synchronized关键字的使用场合:可以作用在代码块和方法两个地方
线程同步:数据永远可以保证准确的,但是效率非常低下
注意:1、如果时非静态方法,此时锁就是该对象的锁
2、如果该方法时静态方法,那么此时锁就是该对象的锁

面试题

synchronized(this){}
此时,获得的是谁的锁?答案:对象自身


synchronized(类.class){}
此时,获得的是谁的锁?答案:类对象自身


public synchronized void 方法(){}
此时,获得的是谁的锁?答案:对象自身


public static synchronized void 方法(){}
此时,获得的是谁的锁?答案:类对象自身
线程同步的方法:wait(),notify(),notifyall()
思考if和while在此处的区别

  1. publicclassThreadStudy{
  2. publicstaticvoid main(String[] args){
  3. PrintResource pr =newPrintResource();
  4. // 定义3个线程
  5. Thread t1 =newThread(()->{
  6. pr.println(“A”,”B”);
  7. });
  8. Thread t2 =newThread(()->{
  9. pr.println(“B”,”C”);
  10. });
  11. Thread t3 =newThread(()->{
  12. pr.println(“C”,””);
  13. });
  14. t1.start();
  15. t2.start();
  16. t3.start();
  17. }
  18. }
  19. classPrintResource{
  20. String current =”A”;
  21. publicsynchronizedvoid println(String str,String next){
  22. //为什么要用while 原因是:需要多次判断,此次,是否应该由 你这根线程来打印
  23. while(!Objects.equals(current, str)){
  24. try{
  25. wait();//等待期间,会释放 线程锁
  26. }catch(InterruptedException e){
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. }
  30. }
  31. System.out.println(str);
  32. current = next;//设置下一个需要打印的
  33. notifyAll();
  34. }
  35. }

leep() 与 wait() 的区别:
(1)、sleep() 是休眠,时间到了会自动唤醒,而wait() 是等待,需要其他线程调用notifyall() 来唤醒
(2)、sleep() 在休眠期间,不会释放线程手上的锁资源,而wait() 在等待期间,会自动释放
(3)、sleep(5000) 意味着:线程一定需要休眠5S钟,而且不会被唤醒
wait(5000)意味着:线程需要等待5S钟,但随时可以被notifyall() 唤醒
连接池:管理和复用连接的池
线程池:管理和服用连接的池
对象池:管理和复用对象池的spring框架!
线程池的组成:1、任务队列:让任务按照queque方式进行排序
2、工作线程:用来执行任务的线程
3任务对接接口:用来接受外部任务的接口
4、线程管理器:用来管理线程的类

Java12.15学习总结 - 图1
简单线程池的用法:Executors.
image.png
复杂线程池ThreadPoolExecutor有七个参数需要记住,面试题!
corePoolSize:初始化多少个线程
maximumPoolSize:最多线程池可以存放多少个线程
keepAliveTime:每根空闲线程,可以在线程中存活多久
Unit:时间单位
WorkQueue:任务队列
TreadFactory:线程工厂,作用是创建线程
Handle:拒绝策略
拒绝策略:当任务队列满了,新任务来临,应该怎么办?
ThreadPoolExecutor.AbortPolicy (默认)新任务来临,直接丢弃,然后抛出异常
ThreadPoolExecutor.CallerRunsPolicy 由提交任务的线程,去执行任务
ThreadPoolExecutor.DiscardOldestPolicy 抛弃 任务队列中等待时间最长的任务,然后将新任务追加到队列的尾部
ThreadPoolExecutor.DiscardPolicy 新任务来临,直接丢弃,不抛出异常
生产者消费模式
使用队列来实现数据通信
队列特点时先进先出
Java12.15学习总结 - 图3
生产者消费者模式借助Queue队列来实现,Queue的父接口是Collection,有顺序要求
优点:生产者、消费者程序可以直接解耦
解决生产者,消费者处理速度不匹配的问题
死锁:多个程序之间,由于无限期等待对方释放锁资源造成程序无法继续运行的过程

二、死锁的4个条件

(1)、一定使用到互斥锁
(2)、不可剥夺,当某根线程持有某个对象的锁以后,其他线程不能剥夺
(3)、相互等待,线程A等待线程B释放,而线程B等待线程A释放
(4)、请求和保持条件 线程A和线程B 都会无限期的不断再次请求获得对应的锁
解决方案:使用具有时效性质的锁