我们继续来聊有关Java的多线程和其等待,休眠,阻塞等相关内容。
一、线程的阻塞与休眠
这就像一个车道,
堵塞是你遭遇了堵车,想开却没法开。
休眠是你根本不想开。
public class BlockingVsSleeping {
private static final Object lock = new Object();
public static void main(String[] args) {
// 线程A:休眠(不释放锁)
new Thread(() -> {
synchronized (lock) {
try {
System.out.println("线程A持有锁,开始休眠3秒");
Thread.sleep(3000); // 休眠但不释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程A释放锁");
}
}).start();
// 线程B:阻塞等待锁
new Thread(() -> {
try {
Thread.sleep(100); // 确保线程A先获得锁
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
System.out.println("线程B获得锁");
}
}).start();
}
}
这展示了一个非常典型的例子,到底是直接被synchronized锁住了堵住没法执行,还是干脆sleep主动不执行。
二、线程六大状态
1. NEW(新建) 2. RUNNABLE(可运行) 3. BLOCKED(阻塞) 4. WAITING(等待) 5. TIMED_WAITING(计时等待) 6. TERMINATED(终止)
1. NEW(新建)
线程被创建,但是没有run或start。系统未分配资源。
2. RUNNABLE(可运行)
线程run或start后,处于执行或可以被执行状态下。
3. BLOCKED(阻塞)
线程等待监视器锁(synchronized锁)(堵车————)
4. WAITING(等待)
线程无限期等待唤醒。
调用以下方法之一:object.wait()
thread.join()
LockSupport.park()
(休息中)
5. TIMED_WAITING(计时等待)
线程等待特定时间。
调用以下带超时参数的方法:Thread.sleep(time)object.wait(timeout)thread.join(timeout)
6. TERMINATED(终止)
线程执行完毕,run结束或异常或stop等。
三、使用否定(!)的方式停掉线程(暂停)
这是一个例子。
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (e.getButton() == 1) { //左键
Ball ball = new Ball(x, y, balls);
balls.add(ball);
} else if (e.getButton() == 3) { //右键
for (int i = 0; i < balls.size(); i++) {
Ball ball = balls.get(i);
ball.start = !ball.start;
}
}
}
我们可以看到,
ball.start = !ball.start;
这一行使用了!的方式来改变线程的是否启动状态。只要start是false的,它就不会被执行,取而代之的是会被执行,不是吗?
实际使用中可以搭配着诸如弹出页面之类来使用。