9、多线程编程
多线程编程
1. 使用方式
通过继承Runnble接口来使用
调用new Thread(this).start;后,会自动执行run()方法里面的内容
2. 线程说明
就绪态:就绪态的资源会主动争夺CUP资源
阻塞态:“睡眠态”,等待被唤醒成为就绪态
-
当我们使用new Thread(this).start;后,JVM会创建一个线程执行,此时这个线程会变成“就绪态”,和主线程一块争夺CUP资源,而不是立即执行!
-
在多个线程“同时”执行时,计算机系统会为让每一个线程“轮流”执行,也就是说,各个线程会处于“走走停停”的状态(加锁后再议)
-
synchronized(锁对象):这个锁里面的代码被称为“临界资源”,同一个锁对象锁所锁住的临界资源只能同时被一个线程执行,当线程执行到锁前的时候,会去检查锁的状态:
- 开:这个线程会进入临界资源,并且会关闭锁
- 关:这个线程会被阻塞,进入阻塞态
通过锁的使用,可以保证临界资源在被某一个线程调用时,不会被打断,可以完整执行里面的代码,当临界资源执行完毕后,会打开锁,并且会唤醒这个锁对应的被阻塞的线程,然后它们在一起争夺cpu资源
测试样例:
public class ThreadOfGeek implements Runnable{
private static int num;
private static Object lock = new Object();
private String threadName;
public ThreadOfGeek(String threadName) {
this.threadName = threadName;
new Thread(this, threadName).start();;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (lock) {
num += 20;
num -= 20;
num++;
System.out.println(this.threadName +":" + num);
}
for(int j = 0; j < 1000 ; j++) {
}
}
}
}
public class TestThread {
public static void main(String[] args) {
new ThreadOfGeek("线程A");
new ThreadOfGeek("线程B");
}
}
两者都在执行完自己的代码后变成就绪态,与另一方争夺cpu资源,进而可能出现以下的局面
部分结果:
3. wait()和notify()以及notifyAll()
wait():让执行这个方法的线程进入阻塞态
notify():唤醒这个锁对应的某一个处于阻塞态的线程
notifyAll():唤醒这个锁对应的所有处于阻塞态的线程
使用方式:
- wait方法必须在同步块中调用,并且必须指定锁对象,如:lock.wait();
- notify和notifyAll方法必须指定锁对象,如:lock.notify();
public class ThreadOfGeek implements Runnable{
private static int num;
private static Object lock = new Object();
private String threadName;
public ThreadOfGeek(String threadName) {
this.threadName = threadName;
new Thread(this, threadName).start();;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (lock) {
num += 20;
num -= 20;
num++;
System.out.println(this.threadName +":" + num);
//唤醒一个处于lock锁状态的线程
lock.notify();
try {
//将自己变成阻塞态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestThread {
public static void main(String[] args) {
new ThreadOfGeek("线程A");
new ThreadOfGeek("线程B");
}
}
上面的代码中,先夺取到cpu资源的一个线程执行临界资源代码后,把另一个线程唤醒(因为只有两个线程被lock锁管理)(第一次没有唤醒对方,因为一开始两者都处于就绪态,但是notify方法也可以执行),再把自己阻塞起来,进而完成了A线程和B线程轮流交替进行的局面
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界