停止线程
测试interrupt中断线程
测试interrupt中断线程
public class Demo {
public static void main(String[] args) {
StopRunnable stopRunnable = new StopRunnable();
Thread t1 = new Thread(stopRunnable);
t1.start();
// 给t1线程有执行时间
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t1.interrupt();
System.out.println("线程已中断");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
class StopRunnable implements Runnable {
@Override
public void run() {
// 利用死循环 测试能不能停止线程
while(true) {
try {
// 沉睡1s
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 休眠1s(写个死循环 让循环执行1s结束)
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < 1000) {
}
System.out.println(Thread.currentThread().getName() + "...run");
}
}
}
测试结果: 不能结束子线程
实际上这个Interrupt() 方法
设置了 isInterrupted 布尔值
如果线程中有wait() 等待 或者 sleep 休眠
这时 调用 interrupt方法
会抛出一个异常 InterruptedException
并且清除中断状态
如果线程中没有等待 或者 休眠
这时调用interrupt方法
会设置中断状态(true/false的改变)
线程中没有等待或睡眠 调用interrupt方法中断线程
public class Demo {
public static void main(String[] args) {
StopRunnable stopRunnable = new StopRunnable();
Thread t1 = new Thread(stopRunnable);
t1.start();
// 给t1线程有执行时间
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t1.interrupt();
System.out.println("线程已中断");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
class StopRunnable implements Runnable {
@Override
public void run() {
// 利用死循环 测试能不能停止线程
while(!Thread.currentThread().isInterrupted) {
// 休眠1s(写个死循环 让循环执行1s结束)
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < 1000) {
}
System.out.println(Thread.currentThread().getName() + "...run");
}
}
}
利用标记 停止线程
利用标记 停止线程
public class Demo {
public static void main(String[] args) {
StopRunnable stopRunnable = new StopRunnable();
Thread t1 = new Thread(stopRunnable);
t1.start();
// 给t1线程有执行时间
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 利用标记 停止线程
stopRunnable.isOver = true;
System.out.println("线程已中断");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
class StopRunnable implements Runnable {
public boolean isOver = false;
@Override
public void run() {
// 利用死循环方式 测试能不能停止线程
while(!isOver) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 休眠1s(写个死循环 让循环执行1s结束)
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < 1000) {
}
System.out.println(Thread.currentThread().getName() + "...run");
}
}
}
测试中断状态 wait方法
public class Demo {
public static void main(String[] args) {
InterruptRunnable it = new InterruptRunnable();
Thread t1 = new Thread(it);
Thread t2 = new Thread(it);
t1.start();
t2.start();
for (int i = 0; i < 50; i++) {
if (i == 25) {
// 调用中断方法 来清楚状态
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(i + "---");
}
System.out.println("主线程结束");
}
}
class InterruptRunnable implements Runnable {
public synchronized void run() {
while(true) {
try {
// 线程1进来 带着锁 遇到了wait方法 等待
//放弃了CPU的执行权 但是 锁 会还回去
// 线程2也带着锁进来 又遇到wait方法 也等待
// 相当于两个线程都在这里等待
// 进入冷冻(中断)状态
// 解决冷冻(中断)状态
// 调用interrupt方法 清除该状态
wait();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "...run");
}
}
}
这里利用interrupt方法 清除冷冻(中断)状态
不会中断线程会强行让线程继续运行
所以报异常后还会打印一次
利用标记法
public class Demo {
public static void main(String[] args) {
InterruptRunnable it = new InterruptRunnable();
Thread t1 = new Thread(it);
Thread t2 = new Thread(it);
t1.start();
t2.start();
for (int i = 0; i < 50; i++) {
if (i == 25) {
// 使用标记
it.isOver = true;
break;
}
System.out.println(i + "---");
}
System.out.println("主线程结束");
}
}
class InterruptRunnable implements Runnable {
public boolean isOver = fales;
@Override
public synchronized void run(){
while(!isOver){
try{
wait();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "...run");
}
}
}
在使用标记法发现当到25的时候 程序不再打印
也不会像调用interrupt方法一样报异常
但是也和调用interrupt方法一样 没有停止线程
说明使用了wait方法 会让 线程等待 放弃了CPU的执行资源
线程就会一直在这里等待
如果想唤醒线程 我们需要调用 notify方法来唤醒线程
wait方法 是 Object类的
报的异常为:IllegalMonitorStateException
这个异常解释中的对象监视器 就是 对象锁
注意: wait方法 必须用锁对象去调用
注意
interrupt方法 进来不要使用
如果要停止线程 直接使用标记法停止
只有遇到了 等待状态 时 可以使用 该方法
强行清除该状态
小练习
Person类 姓名 性别
开启两个线程
一个对Person对象进行赋值
一个对Person对象进行打印
要求 一次打印 小明 男
一次打印 xiaoming nv
间隔输出
public class Demo {
public static void main(String[] args) {
}
}
// Person类 姓名 性别
class Person {
public String name;
public String gender;
//声明标记 来切换 打印 和 赋值
}
// 赋值线程
class SetRunnable implements Runnable {
// 利用成员变量 操作同一个对象
private Person p;
// 定义一个标识 通过改变标识来进行间隔赋值
Private boolean isTrue = true;
// 利用构造方法来赋值
public SetRunnable() {
}
public SetRunnable(Person p){
this.p = p;
}
@Override
public void run() {
while(true) {
//多个线程 操作共享数据
// 添加同步锁 解决数据安全问题
// 为了保证两个同步锁的锁对象相同 使用传进来的p的对象
// 赋值线程 需要赋值完毕 打印线程才能去打印
// 打印线程 打印完毕 才能让赋值线程 去赋值
// 赋值的时候 打印线程 在等待 等赋值完成了 才能去打印
// 打印完成后 通知复制线程 让复制线程继续赋值
//wait 和 notify 使用一个标记来进行切换
// 这个标记要给赋值线程使用 也要给打印线程使用
// 必须保证使用的是同一个标记 标记声明在Person类中
synchronized(p) {
// 先不进入等待 要先进行赋值
if(p.flag == true) {
// 进行等待
try{
p.wait();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 间隔赋值
if(isTrue) {
p.name = "小明";
p.gender = "男";
}else{
p.name = "xiaoming";
p.gender = "nb";
}
// 改变标识符
isTrue = !isTrue;
// 修改标记
p.flag = true;
// 唤醒线程
p.notify();
}
}
}
}
// 打印线程
class PrintRunnable implements Runnable {
// 利用成员变量 操作同一个对象
private Person p;
//利用构造方法 来赋值
public PrintRunnable() {
}
public PrintRunnable(Person p) {
this.p = p
}
}
@Override
public void run(){
while(true){
synchronized(p) {
if(p.flag == false) {
// 进入等待
try{
p.wait();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 打印名字 和 性别
System.out.println(p.name + "..." + p.gender);
// 修改标记
p.flag = false;
// 唤醒线程
p.notify();
}
}
}