type
status
date
slug
summary
tags
category
icon
password
线程相关的概念
什么是线程?
Thread,操作系统进行运算调度的最小单位,它被包含到进程当中,是进程中的实际运行单位。
一个进程可以有多条线程,每条线程并行执行不同的任务。
什么是多线程技术?
是指从软件或者硬件上实现多个线程并发执行的技术。
具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提成性能。
并发和并行
并发:在同一时刻,有多个指令在cpu上同时执行。
并行:在同一时刻,有多个指令在cpu上交替执行。
进程和线程
进程:进程实体的运行过程,是系统进行资源调度和分配的一个独立单位。
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。
动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行。
多线程的实现方式
多线程的三种实现方式
继承Thread类的方式进行实现。
实现Runnable接口的方式进行实现。
利用Callable和Future接口方式实现。
第一种方式的实现:继承Thread类
定义一个MyThread类继承Thread类
在MyThread类中重写run()方法。
创建MyThread类对象。
线程对象调用.start() 启动线程 。
两个小问题
为什么要重写run()方法?
因为run()是用来封装被线程执行的代码。
run()和start()有什么区别?
如果调用run那么和普通的对象调用方法没啥区别,没有开启线程。
如果调用start就是正常的线程启动,有进程的特点。
第二种方式的实现:实现Runnable接口
定义一个MyRunnable实现Runnable接口。
在MyRunnable类中重写run()方法。
创建MyRunnable类的对象。
创建Thread类的对象,把MyRunnable对象作为构造方法的参数。
启动线程。
第三种方式实现:Callable和Future
定义一个类MyCallable实现Callable接口。
在MyCallable类中重写call()方法。
创建MyCallable类的对象。
创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数。
创建Thread类的对象,把FutureTask对象作为构造方法的参数。
启动线程。
get方法的注意事项
类加载器:
三种线程对比
设置和获取线程名
线程默认的名字是 Thread-编号(Thread-0/1/2)
获取线程名字:
String getName()
:返回线程的名称。Thread类中设置线程的名字
void setName(String name)
:将此线程的名称更改为等于参数name;也可以通过构造方法进行设置。
用构造方法给线程命名
实例化构造函数
线程的获取,休眠和调度
获取当前线程对象
public static Thread currentThread():
返回正在执行的线程对象的引用。适用范围:实现Runnable接口;因为Runnable中无getName。
线程休眠
public static void sleep(long time):
让线程休眠指定的时间,单位毫秒。线程调度:
分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片。
抢占式调度模型:优先让优先级高的线程使用CPU,如果线程优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些。
java线程调度的实现
如同时声明两个线程他们的线程默认都是5,若自己先设置则优先级小的会先执行。
最大优先级10,最小1,正常5. 优先级大的获取cpu的能力更高。
后台线程/守护线程
目的:为了守护普通线程而存在。普通线程结束,则守护线程结束,守护线程会挣扎一会再结束。
public final void setDaemon(boolean on)
:设置为守护线程。线程安全
线程安全——买票案例
线程的安全问题
安全的思考
在执行的2和3前的时候,cpu的执行权可能会跑偏,此时ticket- - ,然后又是这样,此时当ticket≤0是退出。
线程安全,同步代码块
为什么会出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
多线程操作共享数据。
如何解决多线程安全问题?
基本思想:让线程没有安全问题的环境。
怎么实现呢?
把多条语句操作共享数据锁起来,让任意时刻只有一个线程执行即可。
java用同步代码块解决。
同步代码块形式:
锁多条语句操作共享数据,可以使用同步代码块实现。
格式:
默认情况是打开的,只要有一个线程进去执行代码了,锁就会关闭。
当线程执行完出来了,锁才会自动打开。
同步的好处和弊端
好处:解决了多线程的数据安全问题
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率
同步代码块例子:
同步的方法:
静态同步方法
Lock锁
JDK5之后提供了一个新的锁对象。
Lock实现提供比使用synchronized方法和语句可以获得更广泛的操作
void lock():获得锁。
void unlock():释放锁。
Lock不能直接实例化,而是采用ReentrantLock来实例化。
ReentrantLock():空参创建一个实例
死锁
产生原因:锁的嵌套;解决:不要写锁的嵌套即可。
生产者和消费者模式概述
两个线程轮流执行,(回合制)
等待和唤醒方法
套路:
- while(true)死循环。
- synchronized锁,锁对象唯一。
- 判断,共享数据是否结束,结束。
- 若没有结束则,则执行其他逻辑。