继承Thread类:
1.自定义线程类继承Thread
2.重写run()方法
3.创建此案城对象,调用start()方法启动线程(以子线程的方式运行run()方法,所以并不会有start()方法的定义)
(不建议使用:避免OOP单继承的局限性)
1 | package com.kuang.lesson01; |
下载网图:
https://www.bilibili.com/video/BV1V4411p7EF?p=4
Runnable接口:
用Thread类来调用start()
好处:方便用一个对象被多个线程调用
1 | package com.kuang.lesson01; |
问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱(线程并发问题)
1 | new Thread(race,"兔子").start();//可以在开启线程的时候给线程起名 |
在run()中用Thread.currentThread().getName()
可以调用本线程的名字
用Thread.currentThread().getName().equals("兔子")
可以验证线程的名字(若为“兔子”则返回true)
用Thread.sleep(100);
来睡眠100毫秒
try……catch一般是产生容易出现问题的操作的时候,系统提示要添加的,读代码的时候可以忽略
Callable接口:
1.实现Callable接口,需要返回值类型
2.重写call方法,需要抛出异常
3.创建目标对象
4.创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
5.提交执行:Future
6.获取结果:boolean r1 = result1.get();
7.关闭服务:ser.shutdownNow();
1 | import org.apache.commons.io.FileUtils; |
Lamda表达式(一步步简化的过程):
定义接口:inertface
1.函数式接口
2.实现类
3.静态内部类
4.局部内部类
5.匿名内部类
6.lambda简化
1 | package com.kuang.lambda; |
1 | package com.kuang.lambda; |
简化参数:
1 | package com.kuang.lambda; |
线程的五大状态:
1.创建状态
2.就绪状态
3.运行状态
4.阻塞状态
5.死亡状态
1–>2:启动线程
2–>3:获得CPU资源
3–>2:释放CPU资源
3–>4:等待程序输入、线程休眠等(sleep等)
4–>2:阻塞接触
3–>5:程序执行完毕
setPriority():更改线程优先级
static void sleep():线程休眠
void join():等待线程终止
static void yield():暂停当前线程,并执行其他线程
void interrupt():中断线程(别用)
boolean isAlive():测试线程是否活动
停止线程:
1.stop()、destroy()方法(JDK提供的,不推荐,已废弃)
2.线程自己停下来
3.使用一个标志位进行终止变量(flag=false时)
比如:某线程的运行是在while(flag)
中的,那么想让线程结束则修改flag为false(写一个方法)
线程休眠:
.Sleep(x);//x毫秒的停止
sleep存在异常,最好抛出(try……catch)
每个对象都有一把锁,sleep不会释放锁
线程礼让:
.yield();
当本线程在运行的时候,暂时停止,让cpu重新调度(选择某个线程进行,但是还是有可能让本线程继续运行)
线程强制执行:
.join();
作用:强制停止主线程的内容,先运行run()的内容(所选中子线程),然后再运行主线程的内容
观测线程状态:
.getState();(虽然输出的时候是下面的单次,但是如果要做==和!=比较的时候,是和THREAD.State.TERMINATED
这样的比较)
NEW:还未启动
RUNNABLE:正在jvm中运行,但是可能正在等待操作系统的其他资源
BLOCKED:受阻塞,并且正在等待监视器锁
WAITING:处于等待状态的线程,正在等待另一个线程执行特定的操作
TIMED_WAITING:正在等待另一个线程执行动作达到指定等待时间
TERMINATED:已退出的线程
线程优先级:
.setPriority();
线程优先级高,则权重大(但是并不是必须先被调用,还是看cpu的分配)(性能倒置)
默认是最大10,最小1,默认给5
先设置优先级再启动
守护线程:deamon
.setDeamon(true);//默认是false表示是用户线程,正常都是用户线程。设为true后,当所有用户线程结束后守护线程自动停止
线程分为用户线程和守护线程
必须等待用户线程执行完毕,不用等待守护线程执行完毕
线程不安全机制:
并发问题:多线程访问通对象并要更改的情况。————》解决方法:等待机制,进入对象的等待池,形成队列+锁
锁机制:synchronized(易造成性能倒置,但是为了安全)
如:后台操作日志,内存监控,垃圾回收等待
不安全案例:
1.抢票的时候,出现多个人买到同一张票的情况
2.有人拿到了-1和0(多个线程在走到判断那一步的时候都是大于0的,然后分别在判断之后取值-1,就有人取到了0,-1的值)(特别是判断和操作之间有sleep的情况)(同样的情况也会造成银行取钱后余额为负数)
3.可能会把两个数组添加到同一个位置(list.add()操作)
补一个javaSE忽略的知识:
创建集合
1 | List<String> list = new ArrayList<String>();//创建一个字符串集合 |
线程不安全的解决方法:
同步方法和同步块:
一.锁:synchronized(Obj){}
1.同步方法:加关键字:synchronized
作用:(我的理解)保证所添加的方法只有一个线程在运行,所以应该锁在增删改查的对象
2.锁块:synchronized(Obj){}
锁的块是变化的量,然后把变化用代码放到里面。
作用:(我的理解)凡是带有synchronized(account){}的内容,只有一个线程能运行
二.直接用安全类(JUC类)
例1:
1 | package com.kuang.syn; |
例2:
1 | package com.kuang.syn; |
死锁:
两个或多个线程互相等待对方的资源,造成都在等待
例:解释:两个都抱着自身的锁,只有运行完才能解锁,但是只有对方解锁才能继续运行(锁的嵌套)
1 | package com.kuang.gaoji; |
解决方法:把代码块拿出来
Lock(锁):JDK5.0开始出现
java.util.concurrent.locks.Lock包
1 | import java.util.concurrent.locks.ReentrantLock; |
线程通信:
wait();
等待,与sleep不同,会释放锁
notify();
处于等待唤醒的状态
线程池:
corePoolSize:核心池的大小
maximumPoolSize:最大线程数
keepAliveTime:线程没有任务时最多保持多长时间后会终止
1 | import java.util.concurrent.ExecutorService; |