多线程
程序:程序是指令和数据的有序集合,是一个静态的概念
进程:执行程序的一次执行过程,是一个动态的概念,进程是资源分配的单位
线程:一个进程中有若干个线程,线程是cpu调度和执行的单位
如:视频中同时可以听声音、看图像、看弹幕
数据紊乱
结果
使代码变得更简洁
去掉一些没有用的代码,只留下核心代码
避免内部类定义过多
函数式接口:一个接口只有一个方法
函数式接口可以使用lambda表达式
五个状态
创建状态: new thread()线程对象一旦创建就进入到新生状态
就绪状态:start() 调用方法后进入,但不意味着立即执行 ,等待cpu的调度执行
阻塞状态:调用sleep,wait或同步锁定
运行状态:进入运行状态,线程才真正执行线程体的代码块
死亡状态:线程中断或者结束,一旦进入死亡,就不能再次启动
模拟网络延时:放大问题的发生性
模拟倒计时
让cpu重新调度,不一定成功,看cpu
合并线程,待此线程完成后,在执行其他线程,其他线程阻塞
少使用,会阻塞
优先级越高,cpu调用的机会越大
daemon
线程分为用户线程和守护线程
虚拟机必须等用户线程执行完毕
虚拟机不用等守护线程执行完毕,只关注用户线程结束后,结束程序
**并发 **
同一个对象被多个线程同时操作
队列和锁
形成线程同步的条件:队列+锁。
每个对象对应一把锁
线程同步是为了安全
同步方法
synchronized方法和synchronized块
控制对象的访问,每个对象一把锁,方法一旦执行,就独占该锁,知道方法返回释放锁
缺陷:会影响效率
锁的对象为变化的量,增删改
某一个同步块同时拥有“两个以上对象的锁”,可能产生死锁的问题。
产生死锁的四个必要条件
互斥条件:一个资源只能被一个进程使用
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
不剥夺条件:进程已获得资源,在未使用完前,不能强行剥夺
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源的关系
显式定义同步锁(手动开启和关闭,别忘记关锁),只有代码块锁
synchronized是隐式锁,出了作用域后自动释放,有代码块和方法锁
reentrantlock类实现了lock
生产者消费者模式
生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件
生产者:没有生产产品之前,需要通知消费者等待,生产产品后,需要通知消费者消费
消费者:消费后,通知生产者生产新的产品以供消费
synchronized可阻止并发更新同一个共享资源,实现了同步,但不能实现不同线程之间的消息传递
wait()
线程一直等待,直到其他线程通知,会释放锁
wait(long timeout)
notify()
唤醒一个处于等待的线程
notifyall()
唤醒同一个对象所有wait的线程,优先级高的线程优先调度
使用线程池,对性能好
提高响应速度
降低资源消耗
便于线程管理
executorservice和executors: