java多线程学习笔记
文章目录
- 关键词
- 1.什么是多线程以及使用场景?
- 2.并发与并行
- 3.多线程实现
- 3.1继承 Thread 类实现
- 3.2Runnable 接口方式实现
- 3.3Callable接口/Future接口实现
- 3.4三种方式总结
- 4.常见的成员方法(重点记忆)9
- 4.1setName/currentThread/sleep要点
- 4.2线程的优先级10档(priority)
- 4.3守护/备胎线程(Daemon)
- 4.4礼让/出让继承(yield又得)了解
- 4.5插入线程(join)了解
- 5.线程的生命周期
- 6.线程的安全问题(synchronized)
- 6.1产生的问题:
- 6.2为什么产生:
- 6.3解决方法:
- 6.3.1同步代码块
- 6.3.2同步方法
- 6.4扩展
- 7.lock锁(jdk5出现)
- 8.死锁
- 9.等待唤醒机制(生产者和消费者)
- 9.1思路分析
- 9.2常见方法(单个桌子实现)
- 9.3吃货与桌子代码
- 9.4厨师和main代码
- 9.5阻塞队列实现
- 厨师吃货类
- 测试类
- 10.java线程状态
关键词
3.1 Thread
3.2 Runnable
3.3 Callable/FutureTask
4 setName()、getName()、currentThread()、sleep()、
setPriority()、getPriority()、setDaemon()、yield()、join()
6 synchronized
7 static Lock lock = new ReentrantLock();
9.2 wait()、notify()、notifyAll()
9.5 ArrayBlockingQueue【put、take】、LinkedBlockQueue
1.什么是多线程以及使用场景?
应用软件种互相独立的,可以同时运行的功能,就形成了多线程
例子:360杀毒软件中,有木马查杀、电脑清理、系统修复、优化加速等可以同时运行的功能
场景:
1.拷贝迁移大文件的时候,多线程可以运行其他功能
2.加载大量资源文件,例如打开游戏时,加载资源文件,加载这些的同时,检查游戏版本,播放背景音乐
2.并发与并行
并发:同一时刻,多条指令在单个CPU交替执行
并行:同一时刻,多条指令在多个CPU同时执行
3.多线程实现
3.1继承 Thread 类实现
每一个创建出来的线程都是独立的,需要共享数据用static修饰常量
从这里可以看出代码是交替执行的(并发)
3.2Runnable 接口方式实现
由于是以参数的形式创建的线程,所以只会创建一次
3.3Callable接口/Future接口实现
3.4三种方式总结
前两种无法获取多线程运行的结果,由于重写的run方法是void,没有返回值,第三种有返回值
4.常见的成员方法(重点记忆)9
4.1setName/currentThread/sleep要点
4.2线程的优先级10档(priority)
关键词:抢占式调度(随机),非抢占式调度
优先级越高,抢到CPU执行权的(概率)越高
参考代码:
4.3守护/备胎线程(Daemon)
备胎线程陆续结束,不会全部执行完毕
应用场景
线程1聊天窗口,要是关闭了,那么线程2没有执行的必要了,所以线程2可以设置成守护线程
4.4礼让/出让继承(yield又得)了解
主要作用:让线程的执行尽可能均匀一点
4.5插入线程(join)了解
5.线程的生命周期
6.线程的安全问题(synchronized)
6.1产生的问题:
1.三个窗口买票共100张,看作三个线程,进行卖票,由于线程独立,导致卖了300张票
2.线程设置static修饰共享,可是依然会有超出范围的票和重复的票被卖出
6.2为什么产生:
**问题1:**例如,设置了sleep,在if条件中满足的都会进入执行代码,线程1执行了+1操作,刚到打印语句,线程2也执行了+1操作,此时,值就是2,那么线程1打印的值为2,线程2也是2
**问题2:**三个线程进入if的时候都满足条件,线程1为99时进入if,没有执行打印语句的时候,++就是100,此时,还没有打印,线程2进入++就是101,再线程3进入就是102
6.3解决方法:
6.3.1同步代码块
把操作共享的代码锁起来,也就是给代码块上锁
**细节1:**synchronzied要写在while里面,不然线程1抢到执行权,那么就会上锁,线程2 3无法执行,线程1解锁,那么100张票已经卖完
**细节2:**锁对象要是唯一的(Object,字节码对象),如果是两把不同的锁,A锁打开进入后关闭,线程1没有来就会一直锁着,线程2进不去,要是有B锁作为锁对象,那么B锁未被占用可以打开进入执行,那么上锁就没有意义了,eg:用this作为锁对象,那么锁就是不唯一的,
6.3.2同步方法
把synchronized关键字加到方法上,配合Runnable接口使用可以不考虑锁对象是否唯一
6.4扩展
StringBuilder:单线程使用,多线程不安全
StringBuffer:多线程使用,相比StringBuilder,该类的方法都是用synchronized进行了同步
7.lock锁(jdk5出现)
用于解决synchronized关键字不能手动枷锁的问题
标准写法
由于线程1执行到break会跳出循环,那么可定不会执行到释放锁的操作,那么线程永远不会停止,我们就可以将lock.unlock()写在finally方法体中,finally会在前面两个执行完成后执行,无论try是否抛出异常,或者catch是否捕获异常
8.死锁
操作系统学过,循环等待,不可剥夺,避免写这样的代码即可
9.等待唤醒机制(生产者和消费者)
9.1思路分析
9.2常见方法(单个桌子实现)
9.3吃货与桌子代码
9.4厨师和main代码
9.5阻塞队列实现
阻塞队列底层已经有锁,不需要再枷锁
厨师吃货类
测试类
10.java线程状态
是没有运行状态的,当线程抢到cpu执行权的时候,就会交给操作系统去管理,jvm就不管了