携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
1. 多线程相关的概念
- 进程:软件静态文件包,系统上程序的动态过程,占用系统资源(CPU、内存、硬盘),进程崩了,会释放资源
- 线程:进程里面最小的执行单元,一个线程有一个自己独立的栈,线程和进程之间可以共享包含他们的进程的空间堆、方法区;线程和线程的栈空间不会,局部变量不会共享;某个线程崩了进程也会崩掉,JVM虚拟机可以开多个线程,线程可以并发执行
2. java中的多线程
- Java中的线程 --> Thread线程类
- package java.lang;
- class Thread implements Runnable;
2.1 run 方法与Start方法的区别
- run()方法知识一个普通的方法,线程对象里面都需要重写它,线程对象.start()开启了一个新的线程,自动调用重写的run()
3. 线程的生命周期
进程中最小执行单元的执行过程,一个 线程拥有一个独立的栈空间
- 新建: new Thread()
- 就绪: 就绪队列排队,抢夺CPU时间片(Java是抢夺式模式)
- 运行: 抢到CPU时间片,就会进入运行状态,当某个线程的CPU时间片用完之后就会回到就绪状态
- 阻塞: 阻塞事件(输入事件、sleep睡眠)主动让出手里的CPU时间片,等待阻塞事件结束回到就绪状态,继续排队抢夺时间片
- 结束: exit();
4. 多线程的实现方式
4.1 实现方式
- 方式一:自定义类继承的方式Thread,重写run()方法 用的不多
- 方式二:自定义类实现接口Runnable接口 更灵活
4.2常用方法
-
public static Thread currentThread() 返回当前线程对象的引用
-
public final String getName() 返回线程的名称
-
public final void setName(String name) 设置线程的名称
-
main线程默认名称是"main", 其他线程默认名称是"Thread-序号",序号从0开始以1递增
-
public static void sleep(long millis) 以传入的毫秒数睡眠 ;
5.1 注意 :静态方法,以当前线程为准,进行方法调用
5.2 醒来之后执行睡前的代码,而不是从头开始
5.3 sleep 需要处理异常,异常不能上抛,只能try,catch 处理,原因:实现了Runnable重写了run方法,子类重写父类的方法不能抛出比父类更广的异常
5. 线程安全
5.1 多线程并发(同时执行)发生数据安全的条件
- 系统支持多线程同时执行
- 共享数据
- 修改(增、减)数据,读取不影响
5.2 解决线程安全的方法:排队
-
同步:synchronized(共享对象)
原理:前面程序没有执行完,后面程序不能执行,效率低,线性安全
附:一步概念 :异步:asynchronized:两端程序同时执行,互不干扰,效率高,有可能不安全
案例:银行(ATM)取钱
演示说明:两个人用同一张卡去银行取钱,如果没有解决线性安全,会出现什么情况,解决了 线性安全又会出现什么情况
看一张分析图
-
代码演示:
//Account :银行卡类
package classes.accountpro;
public class Account {
private String name;
private double balance;
public Account() {
}
public Account(String name, double balance) {
this.name = name;
this.balance = balance;
}
// 取钱方法
public void getMoney (double money) {
synchronized(this){
setBalance(this.balance-money);
System.out.println(Thread.currentThread().getName()+"卡上余额为:"+this.balance);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
// 测试类,这里用的是 Extends 继承Thread 创建的线程
package classes.accountpro;
public class Text {
public static void main(String[] args) {
Account account = new Account("1243571239",10000);
// Ta ta = new Ta(account);
Thread ta = new Ta(account);
Thread tb = new Tb(account);
ta.setName("ta");
tb.setName("tb");
ta.start();
tb.start();
tc.start();
}
}
class Ta extends Thread{
private Account act;
public Ta(Account act) {
this.act = act;
}
@Override
public void run() {
double money = 5000;
act.getMoney(money);
}
}
class Tb extends Thread{
private Account act;
public Tb(Account act) {
this.act = act;
}
@Override
public void run() {
double money = 5000;
act.getMoney(money);
}
}
运行结果图:出现了四种可能
总结
通过案例分析,线程的知识还是有些清晰的,但是线程问题并不好解决,多线程,就会出现很多不符合常规的情况,可以通过synchronize 进行解决,问题解决了但是这又影响了效率,还有一些问题,如何让所有线程都同步???sleep 在什么场景下使用呢? 还要继续学习!
\