1、任务、进程、线程
任务:字面意思,是一个抽象概念。
进程:进程就是操作系统执行的一个程序,程序是静态的代码段,进程是操作系统执行该代码段的一个具象。
线程:线程是一个进程中的某个代码段执行分支,一个进程可以由一个线程组成,可以由多线程组成,多线程执行过程由cpu调度,多线程表面上是并行执行,实际上是串行执行的。
2、创建线程的三种方式
(1)Thread类继承方式
自定义线程类,继承Thread类,并重写run()方法,在他处创建该自定义线程类实例,并调用其start()方法。
(2)实现Runnable接口
自定义线程类,实现Runnable接口,并重写run()方法,在他处创建该自定义线程类、Thread类实例,将前者传入后者,并调用后者的start()方法。
(3)实现Callable接口
一般不用,略
ps
线程池使用方法:
参考:
https://www.cnblogs.com/dolphin0520/p/3932921.html
https://www.cnblogs.com/superfj/p/7544971.html
3、线程状态
1、调用new Thread()后,线程对象被创建,进入"新生状态"
2、调用start()方法后,线程进入"就绪状态",等待cpu调度
3、当cpu开始执行该线程对象的代码体,线程进入"运行状态"
4、当调用sleep()、wait()、或者同步锁时,线程进入"阻塞状态";当阻塞状态解除后,进入"就绪状态",继续等待cpu调度
5、当线程终端或代码执行结束,线程进入"死亡状态",不能再次启动
4、线程类的常用方法
1、setPriority(int newPriority) | 更改线程优先级 2、static void sleep(long millis) | 指定毫秒数内让正在执行的线程休眠,不会释放线程锁 3、void join() | 等待线程终止,线程插队,阻塞其他线程,优先执行完该线程 4、static void yield() | 暂停当前正在执行的线程对象,使该线程重新回到就绪状态,礼让 5、void interrupt() | 中断线程(别用这种方式) 6、boolean isAlive() | 测试线程是否处于活动状态
5、线程通信
(1)管程法
通过设计缓冲区实现。
例如“生产者-消费者模型”中,生产者观测缓冲区产品是否存满,满则停产等待,未满则持续生产;消费者观测缓冲区是否有存货,有则消费,无则等待。
(2)信号灯法
通过设置flag位实现。
例如“演员-观众模型”中,演员表演作品并将flag置位,观众观看作品并将flag复位。
6、线程安全
多个线程同时访问同一个对象,可能引起线程不安全的情况,会造成数据紊乱。一般推荐使用方法来访问对象中的变量,对其进行增删改查
(1)同步方法
使用关键字"synchronized"修饰访问不安全对象的方法,将方法锁定,使其访问的对象变量被有序访问;
(2)同步块
使用关键字"synchronized"修饰不安全的变量,对后续代码块中待访问的对象进行锁定,使其被有序访问;
* ps:同步方法可能会造成性能问题,因为可能锁上过多的变量,同步块比较灵活
(3)lock锁显式实现线程安全
private ReentrantLock lock = new ReentrantLock();
// 以下代码在不安全的访问方法中调用
{
lock.lock(); // 加锁
lock.unlock(); // 解锁
}
lock参考:
https://cloud.tencent.com/developer/article/1680225
https://www.cnblogs.com/myseries/p/10784076.html