本篇文章主要讲述这四个方法的一些特性,stop()和interrupt()是看冰河大佬笔记中的讲解才尝试验证的。而sleep()和wait()是自己一直想整理的,关于其是否释放CPU以及是否释放锁
1.stop()
强制停止线程
会释放synchronized锁
/*** stop方法会释放 synchronized* stop方法不会释放ReentrantLock*/@Testpublic 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*/@Testpublic 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会释放*/@Testpublic 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*/@Testpublic 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书上所说*/@Testpublic 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()**那行紧接着运行释放锁
@Testpublic 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()。但是下面这个程序这样调会出现异常的。@Testpublic 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()那行继续往下运行
这个想必不用解释吧!
/****/@Testpublic 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()走完就往下走的,线程会终止
 
