线程中断innterrupt(未完结)

signalAll()和synchronized

当我试着使用lock来控制锁的,发现以下有趣的现象

public class WaxOMatic {

    public static void main(String[] args) throws InterruptedException {
        Car car = new Car();
        ExecutorService s = Executors.newFixedThreadPool(2);
        s.execute(new Thread(new WaxOn(car)));
        s.execute(new Thread(new WaxOff(car)));
        TimeUnit.SECONDS.sleep(5);
       // s.shutdownNow();


    }

}

class Car {

    private boolean waxOx = false;
    Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();


    public synchronized void waxed() {
       /* lock.lock();
        try {*/

            waxOx = true;
            notifyAll();
//            condition.signalAll();
       /* } finally {
            lock.unlock();

        }*/

    }


    public void buffed() {
        lock.lock();
        try {
            waxOx = false;
//            notifyAll();
            condition.signalAll();
        } finally {
            lock.unlock();

        }

    }


    public /** synchronized */
    void waitForWaxing() throws InterruptedException {
        lock.lock();
        try {
            System.out.println();
            while (waxOx == false) {
                System.out.println("waitfor ..... ");
//                wait();
                condition.await();
            }
        } finally {
            lock.unlock();

        }
    }


    public /** synchronized */
    void waitForBuffing() throws InterruptedException {
        lock.lock();
        try {
            while (waxOx == true) {
//                wait();
                condition.await();
            }
        } finally {
            lock.unlock();

        }
    }
}


class WaxOn implements Runnable {

    private Car car;

    public WaxOn(Car car) {
        this.car = car;
    }


    @Override
    public void run() {
        while (!Thread.interrupted()) {
            System.out.println("start wax  on .....");
//            System.out.println("name = " + Thread.currentThread().getName());
            try {
                TimeUnit.MILLISECONDS.sleep(200);
                car.waxed();
                System.out.println(" --- wax ----");
                car.waitForBuffing();

            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();
            }

            System.out.println("end waxing ......");

        }

    }
}


class WaxOff implements Runnable {

    private Car car;

    public WaxOff(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        System.out.println("start buffed ...");
        try {
            while (!Thread.interrupted()) {
                car.waitForWaxing();
                System.out.println(" ---- buf ---");
                TimeUnit.MILLISECONDS.sleep(200);
                car.buffed();

            }

        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        } finally {

        }
        System.out.println("end buffed /...");

    }
}

可以看到waxed()方法,使用了synchronize获取锁,其他则使用了lock,
在执行过程中,发现,WaxOn给Car加工后按理说应该唤醒WaxOff了,因为在加工完成后,调用了notifyAll(),并且改变控制信号错失的值为true,随后自己进行await(),但是却没有唤醒WaxOff()方法.

这里写图片描述

第一行表示WaxOf已经给Car开始加工了
第二行语句代表WaxOff已经启动,因为因为需要等待WaxOn加工后所以才能操作,所以进入await(),等待被WaxOn加工完成,唤醒执行
第三行,这样WaxOn中加工已经完成了,一直在等待WaxOff执行
但是WaxOff却没有被唤醒执行后续的加工,整个线程被锁了

我们用jstack看看状态
这里写图片描述

可以看到,WaxOff还在等待WaxOn的加工完成的唤醒,由于WaxOn加工后进行了notifyAll,但是却并没有唤醒,使WaxOff一直陷入waiting,然后WaxOn加工后自己也进入了waiting,等待被WaxOff处理。所以这里我们看到了两个线程都进入了waiting,都需要被对方等待唤醒,但却永远不会有操作,陷入了死锁.

原因

因为waxed使用synchronized获取锁,而其他则使用了lock,由于synchronized和lock获取锁的方式不同,condition 来自于某个lock.,通过lock.lock()获取锁,object 通过.synconize() 获取锁,这样就导致他们获取的不是同一个锁,释放了锁,但是却不是对方所需要的锁,故而对着需要该锁的当前线程的notifyAll并不是对方的notifyAll。

中断注意事项

public class WaxOMatic {

    public static void main(String[] args) throws InterruptedException {
        Car car = new Car();
        ExecutorService s = Executors.newFixedThreadPool(2);
        s.execute(new Thread(new WaxOn(car)));
        s.execute(new Thread(new WaxOff(car)));
        TimeUnit.SECONDS.sleep(5);
        s.shutdownNow();


    }

}

class Car{

    private boolean waxOx = false;


    public synchronized void waxed(){
        waxOx = true;
        notifyAll();

    }


    public synchronized void buffed(){
        waxOx = false;
        notifyAll();

    }


    public synchronized void waitForWaxing() throws InterruptedException {
       while (waxOx == false) {
           wait();
       }
    }


    public synchronized void waitForBuffing() throws InterruptedException {
        while (waxOx == true){
            wait();

        }
    }
}


class WaxOn implements Runnable{

    private Car car;

    public WaxOn(Car car) {
        this.car = car;
    }



    @Override
    public void run() {
        while (!Thread.interrupted()){
            System.out.println("start wax  on .....");
            System.out.println("name = " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
                car.waxed();
                System.out.println(" --- wax ----");
                car.waitForBuffing();

            } catch (InterruptedException e) {
                e.printStackTrace();
               // Thread.currentThread().interrupt();
            }

            System.out.println("end waxing ......");

        }

    }
}


class WaxOff implements Runnable{

    private Car car;

    public WaxOff(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        System.out.println("start buffed ...");
        try {
            while (!Thread.interrupted()){
                car.waitForWaxing();
                System.out.println(" ---- buf ---");
                TimeUnit.MILLISECONDS.sleep(200);
                car.buffed();

            }

        } catch (InterruptedException e) {
            e.printStackTrace();
           // Thread.currentThread().interrupt();
        } finally {

        }
        System.out.println("end buffed /...");

    }
}

以上代码是thinking in java中的demo,发现一个奇怪的问题,线程在中断后有一个奇怪现象,在执行中断操作后,线程又重新跑了一次。
这里写图片描述

经过思考原因,反复论证,中断操作对于 I/O,尝试获取锁无法中断,对于sleep,wait等的阻塞状态中断会发生InterruptedException异常,在这里我们需要处理中断,Thread.currentThread().interrupt();//重新设置中断标示位,让线程从阻塞中退出。
这里写图片描述

如图,加上中断处理

这里写图片描述

设置中断位后,都已经结束了.线程也没有挂起,中断起到作用了。

总结

对于处于wait(),sleep,join等操作的线程,如果被调用interrupt()后,会立即重置中断位为false和抛出InterruptedException,因为线程为了处理异常已经重新处于就绪状态。,再一次重新启动的原因就是这个,线程在触发中断的异常后,便会再让这个线程重新处于就绪,重新执行。可以再捕获InterruptedException后return,break或者再一次Thread.interrupted()再次设置中断位也可以起到中断线程的作用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值