Java高级-多线程
- 多线程创建
- 多线程通讯
- 线程池
1.多线程创建
图 图-
- thread/runnable
图:
- 继承Thread类, new对象,对象.start();new Thread(){ run()}.start()
- 实现Runnable,new Thread(Runnable).start();
- 调用了start方法之后,并不是立即执行了多线程代码,这是由操作系统决定的
- thread/runnable
-
- 两种启动线程方法的区别
- 共同点:
必须调用thread产生线程,调用strart方法执行
- 共同点:
- 区别:
继承Thread类, java是单继承,而Runnable是接口,要灵活,Runnable代码可以被多个线程共享
适用多个相同的代码处理同一个资源的问题
- 区别:
- start方法和run方法的区别
start启动线程,就绪状态,run只是个普通方法
- start方法和run方法的区别
2.多线程通讯
- synchronized关键字
- sleep/wait
- wait/notify机制
1.synchronized关键字
图 图 图 图 图- 对象锁,锁住当前对象
图:对象方法上的的synchronized和对象方法里头的synchronized 都是锁住的本对象
- 对象锁,锁住当前对象
- synchronized来实现线程间的通信
图;共享内存变量,该变量内部方法synchronized 锁住
- synchronized来实现线程间的通信
- synchronized 和volitile
线程有独立的内存拷贝, 一个对象的属性int i,一个线程更改了,另一个线程去取,可能取的是线程拷贝(旧数据)主缓存
如果volatile int i;则获取的数据都是主内存,不会拷贝数据到其他线程内存中
区别:
synchronized 获取,释放都有一个监听器对象,线程会从监听器中获取锁,直到线程解锁,线程读取主内存变量,使内存数据有效, 更改数据后返回给主内存, 释放锁
volatile 指管理一个变量值,synchronized管理所有变量值,使用到属性,方法上
- synchronized 和volitile
- synchronized /lock
lock需要 开启是关闭 两个方法 lock ,finally ->unlock
synchronized 是java虚拟机执行的,重量级操作,悲观锁机制,线程获得的是独占锁,其他线程只能阻塞等待
lock是java自己写的:乐观锁,每次不加锁,假设没有冲突,如果操作失败,就重试,直到完成操作
- synchronized /lock
2.sleep /wait
- sleep 机制是 Thread的 native方法,在设定时间内阻塞线程执行,不会去改变线程锁的持有情况
- wait,是需要锁控制的
3.wait/ notify 机制
- wait方法定义在Object 大类中,需要在同步代码块中调用,调用完之后释放锁,并进入锁对象的等待队列,需要线程调用notify方法之后,它才能去重新竞争这个锁。等待锁,竞争锁
- notifyAll :通知所有线程
3.线程池
- 好处
- ThreadPoolExecutor
- 线程池的工作流程
1.好处
- 降低资源消耗:通过重复利用已创建的线程来降低线程 创建,销毁带来的消耗
- 提高响应速度:任务达到一定量级时,不需要等待线程创建
- 提高线程的可管理性。线程池可以做到统一的分配
2.ThreadPoolExecutor
图 图- new ThreadPoolExecutor(corePoolSize,maximunPoolSize,keepAliveTime,miiliseconds,runnableTaskQueue,handler)
图:
7个参数:
corePoolSize:线程池的基本大小,核心数
maxmunPoolSize:最大线程数量,队列满了,不再创建
keepAlivetTime:线程活动保持的时间,工作空闲之后,需要设置一个生命的时间
TimeUnit unit:保命时间单位
BlockingQueue<Runnable> workQueue:阻塞队列
ThreadFactory threadFactory,用于创建线程的工厂
RejectedExecutionHandler:队列和线程满了,整个线程饱和状态,必须采取新的策略处理,
1.常用策略:当满了直接抛出异常
创建线程池-》提交任务
3.线程池的工作流程
- 当提交一个新的任务到线程池
- 首先线程池判断基本线程池是否已满,如果满,就会进入下一个流程,如果没满就会创建一个工作线程来执行任务,工作线程就是子线程
- 其次线程池判断工作队列是否已满,如果没满就会将任务存储到该工作队列中进行相应的数据
- 最后线程池判断整个线程池是否已满,如果没满就会创建新的工作线程来执行任务,满了就会交给我们的 饱和策略来处理
网友评论