[Java并发编程]之二十:并发新特性―Lock锁和条件变量(含代码)(二)

2014-11-24 07:37:05 · 作者: · 浏览: 3
nterruptibly();//获取响应中断锁 try { //更新对象的状态 //捕获异常,必要时恢复到原来的不变约束 //如果有return语句,放在这里 }finally{ lock.unlock(); //锁必须在finally块中释放 }

这里有一个不错的分析中断的示例代码(摘自网上)

当用synchronized中断对互斥锁的等待时,并不起作用,该线程依然会一直等待,如下面的实例:

public class Buffer {

    private Object lock;

    public Buffer() {
        lock = this;
    }

    public void write() {
        synchronized (lock) {
            long startTime = System.currentTimeMillis();
            System.out.println(开始往这个buff写入数据…);
            for (;;)// 模拟要处理很长时间    
            {
                if (System.currentTimeMillis()
                        - startTime > Integer.MAX_VALUE) {
                    break;
                }
            }
            System.out.println(终于写完了);
        }
    }

    public void read() {
        synchronized (lock) {
            System.out.println(从这个buff读数据);
        }
    }

    public static void main(String[] args) {
        Buffer buff = new Buffer();

        final Writer writer = new Writer(buff);
        final Reader reader = new Reader(buff);

        writer.start();
        reader.start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                long start = System.currentTimeMillis();
                for (;;) {
                    //等5秒钟去中断读    
                    if (System.currentTimeMillis()
                            - start > 5000) {
                        System.out.println(不等了,尝试中断);
                        reader.interrupt();  //尝试中断读线程
                        break;
                    }

                }

            }
        }).start();
        // 我们期待“读”这个线程能退出等待锁,可是事与愿违,一旦读这个线程发现自己得不到锁,
        // 就一直开始等待了,就算它等死,也得不到锁,因为写线程要21亿秒才能完成 T_T ,即使我们中断它,
        // 它都不来响应下,看来真的要等死了。这个时候,ReentrantLock给了一种机制让我们来响应中断,
        // 让“读”能伸能屈,勇敢放弃对这个锁的等待。我们来改写Buffer这个类,就叫BufferInterruptibly吧,可中断缓存。
    }
}

class Writer extends Thread {

    private Buffer buff;

    public Writer(Buffer buff) {
        this.buff = buff;
    }

    @Override
    public void run() {
        buff.write();
    }
}

class Reader extends Thread {

    private Buffer buff;

    public Reader(Buffer buff) {
        this.buff = buff;
    }

    @Override
    public void run() {

        buff.read();//这里估计会一直阻塞    

        System.out.println(读结束);

    }
}

执行结果如下:

\ 我们等待了很久,后面依然没有输出,说明读线程对互斥锁的等待并没有被中断,也就是该户吃锁没有响应对读线程的中断。 我们再将上面代码中synchronized的互斥锁改为ReentrantLock的响应中断锁,即改为如下代码:

import java.util.concurrent.locks.ReentrantLock;

public class BufferInterruptibly {

    private ReentrantLock lock = new ReentrantLock();

    public void write() {
        lock.lock();
        try {
            long startTime = System.currentTimeMillis();
            System.out.println(开始往这个buff写入数据…);
            for (;;)// 模拟要处理很长时间    
            {
                if (System.currentTimeMillis()
                        - startTime > Integer.MAX_VALUE) {
                    break;
                }
            }
            System.out.println(终于写完了);
        } finally {
            lock.unlock();
        }
    }

    public void read() throws InterruptedException {
        lock.lockInterruptibly();// 注意这里,可以响应中断    
        try {
            System.out.println(从这个buff读数据);
        } finally {
            lock.unlock();
        }
    }

    public static void main(String args[]) {
        BufferInterruptibly buff = new BufferInterruptibly();

        final Writer2 writer = new Writer2(buff);
        final Reader2 reader = new Reader2(buff);

        writer.start();
        reader.start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                long start = System.currentTimeMillis();
                for (;;) {
                    if (System.currentTimeMillis()
                            - start > 5000) {
                        System.out.println(不等了,尝试中断);
                        reader.interrupt();  //此处中断读操作
                        break;
                    }
                }
            }
        }).start();

    }
}

class Reader2 extends Thread {

    private BufferInterruptibly buff;

    public Reader2(BufferInterruptibly buff) {
        this.buff = buff;
    }

    @Override
    public void run() {

        try {
            buff.read();//可以收到中断的异常,从而有效退出    
        } catch (In