多线程:多条流程同时进行的技术
方式1:
调用start()方法也是告诉CPU 我们是以线程的形式进行操作的
如果直接调用run方法
那么CPU就默认你是单线程进行的 那么这里打印子永远快于父
Thread t=new MyThread();
这是一种多态的形式:只要是继承于Thread类的所有子类都可以通过它进行new出对象
这里new出来了MyThread类对象
子线程和父线程同时进行:
打印时:有可能子线程快于父线程 也可能父快于子
第二点演示:
把主线程放置前面时 会造成一个单线程的效果
切换为中文:
为什么把MyRunnable的任务对象交给Thread处理?
因为MyRunnable实现了Runnable接口
并且用Runnable new了一个新对象
target这个对象引用是属于类 Runnable的
由于Thread的参数是Runnable类型 因此可以把target这个任务对象交给Thread处理
Thread t =new Thread(target);
new出一个新对象 这个对象引用是t
t.start()表示调用子线程开始执行
同时父线程也开始执行 那么就形成了多线程
并且多了一层对象的包装
注意:
我们改变了一下形式:
new后面的那一块都是属于对象target的
之后把target给第4处
之后调用start()方法 它会启动run方法 那么子线程启动
之后继续执行主线程循环
1.
2.
3.
4.
以上这四个线程是同时执行的
存在的问题:
由于这里是泛型 我们可以把泛型定义为String 那么返回类型就是String
并且在作用时也是String类型
这里的try catch语句主要是为了避免在它发生异常的时候 我们还是进行
这里用这个语句是为了在异常的时候我们能够发现并且及时阻止 执行catch语句
由结果可知:我们这里是可以返回结果的
t.start();这个调用执行的是run()方法
调用之后 并且主线程也随着调用执行
这三个线程的执行调用速度是不可预知先后顺序的
我们可以知道Thread是MyThread的父类
那么在子类的构造器中 我们可以通过super调用父类的有参构造器参数name
用super把name送给父类的有参构造器
那么当我们new对象的时候传参
即:Thread t1=new Mythread("1号"); 这是多态的书写形式 t1此时被命名
重新定义名字
currentThread表示谁调用它 它就代表哪一个线程
线程安全问题:
多线程同时发生
先模拟安全问题:
线程安全如何解决?
当一个线程进来访问完毕之后 锁才可以解开
加锁的方式有很多种:
1.
如何上锁呢?全部选种 ctrl+alt+t键 选择第九个
这个锁必须满足锁的唯一性:
那么我们可以用字符串常量 因为它是存在于字符串常量池中的
所以它是唯一的 无论是对于 小明还是小红
但是这把锁是不行的 因为不只有小明和小红一家人去取钱
如图 他们会把小黑小白的账户也锁着了
因此我们用this来作为锁 this==acc
这个是代表账户 每一家人的账户是不同的 因此this代表的账户也是不同的
因此锁也是不相同的
类Account是唯一的
所有线程都是通过这个类来调用的 假设有100个线程 那么只有一个线程可以进来
访问完毕之后才会开锁
2.同步方法
3.
Lock锁:它能更自由的执行何时上锁 何时解锁
final修饰的变量只能被初始化一次
finally代码块中的语句是一定会被执行的
重点:
线程池:
原理:
举个例子:
只有三个线程在进行工作
当处理完手头工作之后它又可以执行后面继续处理后面的任务
这样就极高的提升了工作效率
第一种方法最重要:
参数一:核心线程就是不会死亡的线程 在执行之后依旧存活完好
参数二:最大线程数就是包括核心线程和临时线程的最大数量
参数三:临时线程就是用完可能就消失的线程
参数四:指定的是临时线程的指定存活时间
参数五:假设你最大线程数为10 当第11个任务出现的时候
你就要把这第11个放到任务队列中进行缓存着的地方
参数六:帮我们创建线程的
参数七:假设你最大线程数为10 当第11个任务出现的时候 你要给出一个解决策略 抛出一个异常
配置一个拒绝策略
举个例子:
有一个kTV 外面有10个座位这十个座位可以坐客人叫做指定的任务队列
我们招聘3个长期工这叫做核心线程 七个临时工这叫做临时线程
假设临时工用2天 这个2天就是参数三
参数六就是招聘员工的人力资源师
当外面十个座位坐满并且我们招聘的员工都在忙的时候来人了
那么就是执行参数七一样的策略
这个get方法要等到f1这个执行完之后才可以进行执行
构建线程池的常用API:
OOM表示是内存溢出的意思
ctrl+alt+delete打开任务管理器
定时器:
delay表示延迟多久执行第一次
当第一次执行完之后 就没有delay延迟了
period表示再每隔多长时间再执行一次 也就是周期
task表示执行的任务
实现定时器:
ok:这个delay为3秒
表示延迟3秒之后执行run方法
到这之后 延迟delay就不再作用了
第一次执行完之后 再每一次间隔period时间段再执行一次run方法
也就是说 一开始先延迟3秒再调用run方法
之后再每一次周期间隔2秒调用一次run方法 中间没有延迟
1.但是这是单线程定时器 当执行一个任务时 后面的任务就要进行等待
2.一个任务一异常其他所有的任务都会挂掉
程序挂掉的过程:
因为这是单线程 不太负责任 当出现异常的时候
它不会进行处理 而是直接把它抛给JVM虚拟机
JVM非常牛逼 直接会把整个程序给挂掉
因此我们引入了:
我们通常就用下面这个定时器
因为这个定时器内部有线程池
因此即使第一个任务没有执行完 第二个任务也会同时执行 不会受到影响
并且当一个任务出错的时候 其他不会受到影响
BBB执行一次 10/0是错误 直接挂掉
原理:
但是CCC不会挂掉 因为这是线程池 不是单线程
他不会把这个异常交给JVM虚拟机 它会自己进行处理
因为它是线程池 也不是单线程 大不了把那个异常的任务线程给挂掉就行
不会把整个程序给挂掉
因此程序不会挂掉
总而言之:
线程池牛逼!!!!
多线程是并发和并行同时进行的
线程的生命周期:
notify表示唤醒操作
当你等待时
即是Waiting或Timed Waiting时 我们必须要notify才可以即刻唤醒它 否则就要持续等待



