线程
程序:是一堆指令的集合.
电脑中安装的所有软件都是程序,例如:QQ,WeChat
进程:运行中的程序就叫进程 - 进程就是资源分配的最小单位
线程:进程中[多个同时在执行]的任务 - cpu的最小调度单位
并行:指两个或两个以上的事物在同一时刻发生(同时发生)
并发:指两个或多个事物在同一时间段内发生
微信聊天:
小z在聊天:
同时收到了两个大老爷们发的信息(9:55分)
小h 和 小f
小z在回复信息:
先回小h: 吃饭了
又回小f: 吃了吗
电脑中处理信息: CPU -> 中央处理器
线程类:Thread
1.线程的概念:
a.进程中[多个同时在执行]的任务
b.主方法程序运行就是打开一个线程 - main方法自带线程
2.创建线程
方式一:
自定义类直接继承Thread类
a.创建自定义类 继承Thread类
b.重写run()
c.在主方法中创建自定义类的对象
d.t.start() 开启线程
总结:一个类只能继承一个类,如果继承了Thread类就变成了单一个线程类,局限性比较大
方式二:
自定义类实现Runnable接口
a.创建自定义类(任务类) 实现 Runnable接口
b.重写run()
c.在主方法中创建任务类对象
d.通过任务类对象,构建线程类对象
e.start()开启线程
总结:一个类实现了Runaable接口后,还可以继承别的类,扩展性功能比较多,局限性没有这么大
使用匿名内部类方式创建线程
匿名内部类结合方式一或方式二
构造方法:
Thread() - 直接创建Thread类
Thread(String name) - 多个Thread线程类是,需要知道线程名字
Thread(Runnable target) - 通过Runnable接口创建
Thread(Runnable target, String name)
3.常用API:
static Thread currentThread() - 获取当前线程对象
String getName() - 返回该线程的名称
int getPriority() - 设置线程的优先级
默认优先级: 5
等级分: 1(最小) ~ 10(最大)
cpu的切换是随机的,设置优先级只能是提高线程先出现的概率
boolean isDaemon() - 询问是否是守护线程
守护线程 - 前台线程
java中GC就是守护线程 - 垃圾回收机制 - 程序开启
Thread.sleep(毫秒值) - 线程休眠时间
线程同步[线程安全]
1.产生原因: 多个线程,共用同一个资源
2.解决办法:加锁 - 线程同步锁 - synchronzied
1)使用线程同步锁
(1)同步方法锁
a.只能同时被一个线程所持有,当这个线程执行完这个方法,才释放锁
b.锁的范围越大,效率越低
c.锁在方法上,其实就是锁this对象
调用方法:
this.方法名()
(2)同步代码块
a.可以选择性将方法中一部分代码进行上锁,同步代码锁,锁的时候需要借助对象进行上锁
b.加锁的对象:对象必须是被所有线程所共享的对象
c.通常用this表示加锁的对象
2)Lock - 接口
(1)实现类:ReentrantLock(可重入锁)
添加锁: lock()
释放锁: unlock()
自行了解(理解原理):
可重入锁
自旋锁
悲观锁/乐观锁
线程状态:
)新建状态(new): new完一个对象
2)就绪状态(Runnable):
a.通过调用start()进入就绪状态
b.run() -> 就绪: cpu时间有关/可分配,可归还
3)运行状态(Running)
cpu时间片分配到的线程就进入运行状态
4)阻塞状态(Block)
join阻塞 -> 让别的线程阻塞
计时等待阻塞 -> Thread.sleep()
wait阻塞
锁阻塞 -> synchronized/Lock
IO阻塞
5)死亡状态(Dead)
线程通信:
形成原因:两个/两个以上线程同时共享数据,两个线程之间会有互相交互的过程
方法:
wait() - 等待
wait(long) - 超过指定时间,自动唤醒 (计时等待)
notify() - 唤醒当前在等待的线程
notifyAll() - 唤醒全部线程
线程池:
1.好处:
a.线程池刚创建出来的时候,线程就已经创建好了,节约创建线程的空间和时间
b.线程池中的对象,使用完毕后没有销毁,而是归还到到了线程池中,可以反复使用
总结:节约内存,提高效率
2.创建线程池方式
newCachedThreadPool() - 创建根据需要线程数量的线程池
newFixedThreadPool(int nThreads) - 创建固定数量的线程池
newScheduledThreadPool() - 创建周期性执行的线程池
newSingleThreadExecutor() - 创建单一线程的线程池
Callable接口 -> Runnable接口 -> 进行优化
1.Callable接口只能应用在线程池中,不能单独创建
2.使用:
a.submit() -> 有返回值 -> 返回值类型Future
b.使用get() -> 接收call()中的返回值
会造成阻塞状态,要一直等待
c.使用get(long,TimeUnit) -> 超时继续
需要处理异常 -> try-catch