多线程
文章目录
进程
进程 就是一个线程的集合
线程
线程都在main函数里面 main是用户创建守护线程
多线程创建
方式一
通过继承Thread重写 run方法 在主线程 调用start 实现并发交替执行
方式二
实现runnable接口
启动线程传入目标对象+thread对象.start
推荐使用 避免了单继承的局限性 灵活方便 方便同一个对象被多个线程使用
方式三
callable
实现callable接口 需要返回值类型
重写call方法需要抛出异常
创建目标对象
创建执行任务 ExecutorService service=Executors.newFixedThreadPool(3);
提交执行 Future<Boolean> r1= (Future<Boolean>) service.submit(t1);
获取结果 boolean rs1=r1.get();
关闭 service.shutdownNow();
静态代理
静态代理模式总结:
真实对象和代理对象都要实现同一个接口
代理对象要代理真实角色
好处
代理对象可以做很多真实对象做不了的事情
而真实对象可以专注的做自己的事情
lambda表达式
接口里面只有一个方法才可以使用 函数式接口
总结
lambda 表达式只能有一行代码的情况下才能简化成为一行 如果有多行 那么就用代码块包裹
前提是函数式接口
多个参数可以可以去掉参数类型 但是要带上括号
停止线程
利用标识位 标识位false 使其停止 不要用官方的stop 官方不建议使用的
礼让线程
礼让就是我进去了 模块 然后退出重新进行就绪 然后如果cpu调度另外一个就礼让成功
Join合并线程
就是将这个线程执行完成后才能执行其他线程 堵塞 插队
Priority线程优先级
可以设置线程优先执行 但主要还是看调度
Daemon守护线程
线程分为 用户线程 和 守护线程
虚拟机必须确保正常线程执行完毕
虚拟机是不需要等待守护线程
比如 后台日志 gc …
线程同步
同步的安全性 线程+锁来解决同步的安全性 synchronize 锁机制
synchronize 关键字
它是一种 锁的机制 对象会得到一把锁 然后去访问 访问结束 本对象释放锁 然后才能下个用户访问
缺点 如果锁了整个类 会导致资源低效
synchronize 代码块 默认锁的是本身 this 谁去做crud操作了就锁谁
锁的对象 就是变化的量 就是要加锁的
CopyOnWriteArrayList 并发包下 线程安全 里面用显式的锁机制
死锁 Dead Lock
- 产生死锁的必要条件
- 互斥条件:一个资源每次只能被一个进程使用
- 请求与保持条件: 一个进程因请求资源而阻塞时,对已获得的资源就保持不放
- 部剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成了一种头尾末接的循环等待资源关系
总结 解决方法 我们只要想办法破其中的任意一个或多个条件就可以避免死锁的发生
LOCK(锁)
ReentrantLock 可重试锁
Synchronized 与 lock 区别
- Lock 是显式锁(手动开启与关闭锁)synchronize是隐式锁 出了作用域自动释放
- lock只有代码块锁 synchronize只有代码块锁与方法锁
- 使用lock锁 jvm将花费较少的时间来调度线程,性能更好,并且具有更好的可拓展性(提供更多的子类)
- 优先使用顺序
- lock>同步代码块(已经进入方法体,分配了相应的资源)>同步方法(在方法之外)
线程消费者与生产者
方法名 | 作用 |
---|---|
wait ( ) | 表示线程一直等待直到其他线程通知,与sleep不同,会释放锁 |
wait(long timeout) | 指定等待的毫秒数 |
notify( ) | 唤醒一个处于等待的状态 |
notifyAll( ) | 唤醒同一个对象上所有调用wait方法的线程,优先级别高的线程优先调度 |
注意:均是object类的方法 都只能在同步方法或者同步代码块中使用,否则会抛出异常IIIegaImonitorstateexception
解决线程通信方法
并发协助模型 “生产者/消费者模式”----->管理法(1)
- 生产者 负责生产数据的模型(可能是方法 对象 线程 进程)
- 消费者 负责处理数据模型(可能是方法 对象 线程 进程)
- 缓冲区 消费者不能直接使用生产者的数据 他们之间有个缓冲区
生产者将生产好的数据放入缓冲区 消费者从缓冲区拿数据
解决方式2
并发协助模型 生产者/消费者—》信号灯法
线程池
-
背景 经常创建与销毁使用量非常大的资源 比如并发情况下的线程,对性能影响很大
-
思路:提前创建好多个线程 放入线程池 使用时直接获取,使用完放回池中 可以避免频繁创建销毁 实现重复利用,类似与生活中的交通工具
-
好处
-
- 提高响应的速度(减少了创建新线程的时间)
- 降低资源消耗(重复利用线程池创建线程,不需要每次都创建)
- 便于线程管理(。。.)
- corePoolSize 线程大小
- maxximumPoolSize 最大线程数
- keepAliveTime:线程没有任务时最多保持多长时间会终止
-
jdk5.0开始提供了线程池相关的ApI:ExecutorServie和Executors
-
ExecutorServie:真正的线程池接口 常见子类ThreadPoolExecutor
-
Void execute(Runnable command):执行任务/命令,没有返回值,一般来执行runnable
-
Futuresubmit(callabletask):执行任务,有返回值 一般又来执行callable
-
void shutdown():关闭线程池
-
Executors:工具类、线程池的工具类,用于创建并返回不同类型的线程池