Java中停止线程、中断线程、等待状态(wait)(基础解析)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Ssssssue/article/details/79284103

http://blog.csdn.net/ssssssue

停止线程

测试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();
            }
        }
    }
展开阅读全文

java线程 wait notify

09-24

源码如下:rn[code=java]rnpublic class TakeAndPour rn public static void main(String args[]) rn WaterTaking wt = new WaterTaking();rn WaterPouring wp = new WaterPouring();rn Thread t1 = new Thread(wt, "Xiaohao");rn Thread t2 = new Thread(wp, "doubi");rn t1.start();rn t2.start();rn rnrnclass Tank rn private static int count = 10; // 缸里原有的水rn //private static int max = 5;rn private static boolean flag = true; //防止同时取水、 倒入水rn public void takeWater() rn synchronized (this) rn while (!flag) rn try rn System.outrn .println("The tank is being used now");rn this.wait();rn catch (Exception e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rn rn rn flag = false; //同一时刻只允许一个对水缸操作rn try rn Thread.sleep(800);rn catch (InterruptedException e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rn rn count--;rn System.out.println(flag+" "+Thread.currentThread().getName()rn + " take out some water" + " now water remain " + count);rn rnrn flag = true; rn this.notifyAll(); //操作完了就把flag置为true,并唤醒线程,这里使用notify()一样。rn rn rn rn public void pourWater() rn synchronized (this) rn flag = false;rn while (!flag) rn try rn System.outrn .println("the tank is being used");rn this.wait();rn catch (Exception e) rn e.printStackTrace();rn rn rn try rn Thread.sleep(800);rn catch (InterruptedException e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rn rn count++;rn System.out.println(flag+" "+Thread.currentThread().getName()rn + " pour in some water" + " now water remain " + count);rn flag = true;rn this.notifyAll();rn rn rn rnrnrnclass WaterTaking implements Runnable rn Tank t = new Tank();rnrn public void run() rn while(true)rn t.takeWater();rn rn rnrnclass WaterPouring implements Runnable rn Tank t = new Tank();rnrn public void run() rn while(true)rn t.pourWater();rn rn rnrn[/code]rnrn但是 现在的结果出现了问题,打印如下:rnthe tank is being used, or the tank is full of water.rnfalse Xiaohao take out some water now water remain 9rnfalse Xiaohao take out some water now water remain 8rnfalse Xiaohao take out some water now water remain 7rnfalse Xiaohao take out some water now water remain 6rnfalse Xiaohao take out some water now water remain 5rnfalse Xiaohao take out some water now water remain 4rnfalse Xiaohao take out some water now water remain 3rn.......rn倒入水的线程,第一下进去就被卡住了,全是取水的线程。求各位帮下忙分析下问题所在,谢了! 论坛

没有更多推荐了,返回首页