一,线程安全问题
1.线程安全问题就是多个线程,同时操作同一个共享资源的时候,可能会出现业务安全问题
2.原因
(1)存在多个线程在同时执行
(2)同时访问同一个共享资源
(3)存在修改共享资源
二,线程同步
1.线程同步就是解决线程安全问题的方案
2.思想:让多个线程实现先后依次访问共享资源
3.加锁
(1)同步代码块
①作用:把访问共享资源的核心代码块上锁,依次保证线程安全
②格式:synchronized(同步锁){}
③原理:每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行
④注意事项:
Ⅰ:对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则锁会失效
Ⅱ:实例方法建议使用this
Ⅲ:静态方法建议使用类名.class(字节码)
(2)同步方法
①作用:把访问共享资源的核心方法给上锁,以保证线程安全
②格式:在方法的返回值类型前加上synchronized
③原理:每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行
④底层原理
Ⅰ:同步方法的底层由隐式锁对象,只是锁的范围是整个方法代码
Ⅱ:如果方法是实例方法,同步方法默认用this作为锁对象
Ⅲ:如果方法是静态方法,同步方法默认用类名.class(字节码)作为锁对象
(3)Lock锁
①Lock是接口,不能直接实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象
②常用方法
Ⅰ:获得锁:lock()
Ⅱ:释放锁:unlock()
三,线程通信
1.当多个线程共同操作共享的资源时,线程间通过某种方式互相告知自己的状态,以互相协调,并避免无效的资源争夺
2.Object类的等待和唤醒方法
(1)wait():让当前线程进入等待并将占用的锁释放
(2)notify():唤醒等待的单个线程
(3)notifyAll():唤醒等待的全部线程
(4)注意:上述方法要使用当前同步锁对象进行调用
四,线程池
1.本质:线程池解锁一个可以复用线程的技术
2.创建线程池
(1)方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象
①ThreadPoolExecutor构造器:public ThreadPoolExecutor()
②构造器的七个参数
Ⅰ:corePoolSize:指定线程池的核心线程数量
Ⅱ:maximumPoolSize:指定线程池的最大线程数量
Ⅲ:keepAliveTime:指定临时线程的存活时间
Ⅳ:unit:指定临时线程存活的时间单位
Ⅴ:workQueue:指定线程池的任务队列
Ⅵ:threadFactory:指定线程池的线程工厂
Ⅶ:hadler:指定线程池的任务拒绝策略
(2)方式二:使用Executors(线程池工具类)调用方法返回不同特点的线程池
(3)注意事项:大型并发系统环境中使用Executors如果不注意可能会出现系统风险
五,并发和并行
1.进程
(1)正在运行的程序就是一个独立的进程
(2)线程是属于进程的,一个进程可以同时运行很多个线程
(3)进程中的多个线程其实是并发和并行执行的
2.并发:进程中的线程是由CPU负责调度执行的,但CPU能同时处理线程的数量有限,为了保证全部线程都能往前执行,CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发
3.并行:在同一时刻,同时有多个线程在被CPU调度执行
六,线程的生命周期
1.Java总共定义了六种状态,都定义在Thread类的内部枚举类中
2.状态分类
(1)NEW(新建):线程刚被创建,但是并未启动
(2)Runnable(可运行):线程已经调用start(),等待CPU调度
(3)Blocked(锁阻塞):线程在执行的时候未竞争到锁对象,进入Blocked状态
(4)Waiting(无限等待):一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能唤醒
(5)Timed Waiting(计时等待):同Waiting状态,有几个方法由超时参数,调用他们进入Timed Waiting状态
(6)Teminated(被终止):因为run方法正常退出而终止,或者因为没有捕获异常终止了run方法而终止