本篇文章主要讲述这四个方法的一些特性,stop()和interrupt()是看冰河大佬笔记中的讲解才尝试验证的。而sleep()和wait()是自己一直想整理的,关于其是否释放CPU以及是否释放锁
1.stop()
强制停止线程
会释放synchronized锁
/**
* stop方法会释放 synchronized
* stop方法不会释放ReentrantLock
*/
@Test
public void testStopAndUnRelease() throws InterruptedException {
Object o = new Object();
Runnable runnable = ()->{
synchronized (o){
try {
System.out.println(Thread.currentThread().getName()+":我获取了锁");
TimeUnit.SECONDS.sleep(10);
System.out.println(Thread.currentThread().getName()+":我释放了锁");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable,"线程A");
Thread thread1 = new Thread(runnable,"线程B");
thread.start();
//确保线程A已获取锁
TimeUnit.SECONDS.sleep(1);
thread1.start();
thread.stop();
System.out.println("线程A已强制停止");
thread.join();
thread1.join();
}
不会主动释放ReetrantLock锁
冰河大佬说不能释放,但是有finally也可以释放的
/**
* 不会释放ReentrantLock
*/
@Test
public void testStopAndUnRelease2() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Runnable runnable = () -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + ":我获取了锁");
TimeUnit.SECONDS.sleep(10);
System.out.println(Thread.currentThread().getName() + ":我释放了锁");
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
};
Thread thread = new Thread(runnable, "线程A");
Thread thread1 = new Thread(runnable, "线程B");
thread.start();
TimeUnit.SECONDS.sleep(1);
thread1.start();
thread.stop();
System.out.println("线程A已强制停止");
thread.join();
thread1.join();
}
/**
* ReentrantLock会释放
*/
@Test
public void testStopAndUnRelease2() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Runnable runnable = () -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + ":我获取了锁");
TimeUnit.SECONDS.sleep(10);
System.out.println(Thread.currentThread().getName() + ":我释放了锁");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
};
Thread thread = new Thread(runnable, "线程A");
Thread thread1 = new Thread(runnable, "线程B");
thread.start();
TimeUnit.SECONDS.sleep(1);
thread1.start();
thread.stop();
System.out.println("线程A已强制停止");
thread.join();
thread1.join();
}
2.interrupt()
标记线程中断
需要代码里主动检测
触发InterruptedException
- wait
- join
-
3.sleep()
关于sleep()的两个问题分别是:
会释放锁吗? 答:不会
-
不会释放锁
/**
* 不会放弃锁
* @throws InterruptedException
*/
@Test
public void testSleepIsReleaseLock() throws InterruptedException {
Object o = new Object();
Runnable runnable = ()->{
System.out.println("外层"+Thread.currentThread().getName());
synchronized (o){
System.out.println(Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":我结束了");
}
};
Thread threadA = new Thread(runnable, "线程A");
threadA.start();
TimeUnit.SECONDS.sleep(1);
System.err.println("开始创建并执行线程B,当前的线程A状态"+threadA.getState());
Thread threadB = new Thread(runnable, "线程B");
threadB.start();
threadA.join();
threadB.join();
}
线程A先启动等待1秒后启动线程B,此时线程A已经获取锁
- 线程B仅仅打印锁外的 外层信息就是卡住了
待A解锁打印结束后,线程B才会进入打印自己的线程名->sleep->释放锁
会释放CPU
/**
* 测试Sleep是否放弃锁和CPU
* 1.会放弃CPU,但是我电脑多核的也不准,结合JVM3书上所说
*/
@Test
public void testSleepIsReleaseAll() throws InterruptedException {
Runnable runnable = ()->{
System.out.println(Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":我结束了");
};
Thread threadA = new Thread(runnable, "线程A");
threadA.start();
TimeUnit.SECONDS.sleep(1);
System.err.println("开始创建并执行线程B,当前的线程A状态"+threadA.getState());
Thread threadB = new Thread(runnable, "线程B");
threadB.start();
threadA.join();
threadB.join();
}
线程A先启动,等一秒后启动的线程B,此时主线程打印了线程A状态为 Timed-Waited
- 线程B启动后,也立即打印,并进入sleep
从实验中其实说明不了什么,因为我的电脑是多核的,线程A可能还一直占着A核心,B去用CPU的B核心也说不定。所以。这里我只能相信《深入理解JVM》的作者了。书上说: 那就是不占CPU
4.wait()
对wait()一直很迷糊
- 是否释放锁? 释放
- 是否释放CPU?释放
- 在哪里可以调用wait()?被
**synchronized**
使用的对象,才可以调用**wait()**
程序调用完wait(),如何唤醒,唤醒完程序从哪里运行? 唤醒后从
**wait()**
那行紧接着运行释放锁
@Test
public void testWait() throws InterruptedException {
Object o = new Object();
Runnable runnable = ()->{
synchronized (o){
System.out.println(Thread.currentThread().getName());
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":我结束了");
}
};
Thread threadA = new Thread(runnable, "线程A");
threadA.start();
TimeUnit.SECONDS.sleep(1);
System.err.println("开始创建并执行线程B,当前的线程A状态"+threadA.getState());
Thread threadB = new Thread(runnable, "线程B");
threadB.start();
threadA.join();
threadB.join();
}
线程A先运行,之后调用wait
- 主线程打印线程A状态会为Waited,并开启B
- 如果不释放锁,B线程启动后名字是打不出来的,但是B启动后立即打印了B线程名
释放CPU
我相信周志明大佬只有被synchronized()的对象可以调
我在最初学习多线程的时候看到最多就是,synchronized
中直接调用wait()
。但是下面这个程序这样调会出现异常的。@Test
public void testWait() throws InterruptedException {
Object o = new Object();
Runnable runnable = ()->{
synchronized (o){
System.out.println(Thread.currentThread().getName());
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":我结束了");
}
};
Thread threadA = new Thread(runnable, "线程A");
threadA.start();
TimeUnit.SECONDS.sleep(1);
System.err.println("开始创建并执行线程B,当前的线程A状态"+threadA.getState());
Thread threadB = new Thread(runnable, "线程B");
threadB.start();
threadA.join();
threadB.join();
}
当时学习的时候调用可以,因为
- 如果synchronized在实例方法上,synchronized锁的是this实例,方法中wait(),自然是this.wait()。
- 如果synchronized是synchronized(this){…},这样也没问题
- 如果synchronized是在static方法上,大家可以试一下,可以使用该类字节码对象的wait()方法
public class MyTest{
public static void sayHello() throws InterruptedException {
MyTest.class.wait();
}
}
从wait()那行继续往下运行
这个想必不用解释吧!
/**
*
*/
@Test
public void testWaitTime() throws InterruptedException {
Object o = new Object();
Runnable runnable = ()->{
int i=0;
System.out.println("外层"+Thread.currentThread().getName());
synchronized (o){
System.out.println(Thread.currentThread().getName());
try {
if (i==0){
System.out.println("waitxxx");
o.wait(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":我结束了");
}
};
Thread threadA = new Thread(runnable, "线程A");
threadA.start();
TimeUnit.SECONDS.sleep(1);
System.err.println("开始创建并执行线程B,当前的线程A状态"+threadA.getState());
Thread threadB = new Thread(runnable, "线程B");
threadB.start();
threadA.join();
threadB.join();
}
- i永远都是0,但是wait()走完就往下走的,线程会终止