线程六个状态:
public enum State { /** * 新生 */ NEW, /** * 运行 */ RUNNABLE, /** *阻塞 */ BLOCKED, /** * 等待 */ WAITING, /** * 超时等待 */ TIMED_WAITING, /** 死亡 **/ TERMINATED; }
synchronized和lock的区别
1、synchronized是关键字,lock是类
2、synchronized全自动获取释放,lock手动
3、synchronized标识后,线程A执行,线程B会一直等待,lock可以中途释放
4、synchronized适合少量的数代码,lock用于大亮代码加锁。
经典问题,生产者、消费者
public static void main(String[] args) { t2 t2 = new t2(); new Thread(() -> { for (int i = 0; i < 50; i++) { try { t2.add(); } catch (InterruptedException e) { throw new RuntimeException(e); } } }).start(); new Thread(() -> { for (int i = 0; i < 50; i++) { try { t2.delete(); } catch (InterruptedException e) { throw new RuntimeException(e); } } }).start(); } int sum = 0; public synchronized void add() throws InterruptedException { //while(sum==0) if (sum != 0) { this.wait(); } sum++; System.out.println(sum + "生产了一个东西"); this.notify(); } public synchronized void delete() throws InterruptedException { //while(sum==0) if (sum == 0) { this.wait(); } sum--; System.out.println(sum + "使用了一个东西"); this.notify(); }
以上代码看着和用着都没问题,问题出在,一旦我多几个线程运行就会出现数据错误:
而且还有几率一直某一个线程处于等待状态,无法被唤醒 :
我的理解是cpu执行的数据很快,假如在某一刻A线程处于等待,B线程也处于等待,此时C线程唤醒了,这两个同时被唤醒,就出现了多次消费,虚假唤醒,其实就只能消费一次。
所以我们不能使用一次if作为判断,应该使用while作为判断,
然后就是使用java多线程包下的Condition ,它也可以阻塞、唤醒线程,它还有一个优势就是可以指定唤醒某一个线程。
package com.quxiao.controller;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @program: package1
* @author: quxiao
* @create: 2023-09-27 15:22
**/
public class t3 {
public static void main(String[] args) {
t3 t3 = new t3();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
t3.a();
}
}, "a").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
t3.b();
}
}, "b").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
t3.c();
}
}, "c").start();
}
int sum = 1;
Lock lock = new ReentrantLock();
Condition aLock = lock.newCondition();
Condition bLock = lock.newCondition();
Condition cLock = lock.newCondition();
void a() {
lock.lock();
try {
while (sum != 1) {
aLock.await();
}
System.out.println(Thread.currentThread().getName()+":" + "AAAA");
sum = 2;
bLock.signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
void b() {
lock.lock();
try {
while (sum != 2) {
bLock.await();
}
System.out.println(Thread.currentThread().getName()+":" + "BBBB");
sum = 3;
cLock.signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
void c() {
lock.lock();
try {
while (sum != 3) {
cLock.await();
}
System.out.println(Thread.currentThread().getName()+":" + "CCCC");
sum = 1;
aLock.signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}