10 Java并发编程3-线程间协作总结

来源:互联网 发布:11式榴弹发射器知乎 编辑:程序博客网 时间:2024/05/29 18:54

一 wait()、notify()、notifyAll()
是Object类中的方法。
1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。
2)调用某个对象的wait方法能让当前线程阻塞,并且当前线程必须拥有此对象的锁。
3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象锁的线程,如果有多个线程都在等待这个对象锁,则只能唤醒其中一个线程。
4)调用notifyAll()方法能够唤醒所有正在等待这个对象的锁的线程。
?为什么是Object类中声明的方法,而不是Thread类?
由于每个对象都拥有锁,所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作。
wait方法、notify方法、notifyAll方法必须在同步块或者同步方法中进行。
调用某个线程的wait()方法,相当于让当前线程交出此对象的锁,然后进入等待状态,等待后续再次获得此对象的锁。
notify()方法能够唤醒一个正在等待该对象的锁的线程,一个线程被唤醒不代表立即获取了对象的锁。

package javazongjie;public class Test3 {    public static Object object = new Object();    public static void main(String[] args) {        Thread1 thread1 = new Thread1();        Thread2 thread2 = new Thread2();        thread1.start();        try{            Thread.sleep(2000);        }catch (InterruptedException e) {            // TODO: handle exception            e.printStackTrace();        }        thread2.start();        /**         *  线程Thread-1调用了object.notify()            线程Thread-1释放了锁            线程Thread-0获取到了锁         */    }    static class Thread1 extends Thread{        public void run() {            synchronized (object) {                try{                    object.wait();                }catch (InterruptedException e) {                    // TODO: handle exception                }                System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁");            }        }    }    static class Thread2 extends Thread {        public void run() {            synchronized (object) {                object.notify();                System.out.println("线程" + Thread.currentThread().getName() + "调用了object.notify()");                System.out.println("线程" + Thread.currentThread().getName() + "释放了锁");            }        }    }}

2 Condition
Condition是在java1.5 中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,实现线程间协作更加安全和高效。阻塞队列实际上使用了Condition来模拟线程间协作。
* Condition是个接口,基本的方法是await()和signal()方法;
* Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
* 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用。
Condition中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll();

3 生产者-消费者模型的实现
* 使用Object的wait()和notify()实现。

package javazongjie;import java.util.PriorityQueue;public class Test4 {    private int queueSize = 3;    private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize);    public static void main(String[] args) {        Test4 test = new Test4();        Producer producer = test.new Producer();        Consumer consumer = test.new Consumer();        producer.start();        consumer.start();        /**         *  向队列中插入一个元素,队列剩余空间:2            向队列中插入一个元素,队列剩余空间:1            向队列中插入一个元素,队列剩余空间:0            队列满,等待有空余空间            从队列取走一个元素,队列剩余2个元素            从队列取走一个元素,队列剩余1个元素            从队列取走一个元素,队列剩余0个元素            队列空,等待数据            //循环输出上述         */    }    class Consumer extends Thread {        public void run() {            consume();        }        private void consume() {            while(true) {                synchronized (queue) {                    while(queue.size() == 0) {                        try{                            System.out.println("队列空,等待数据");                            queue.wait();                        }catch (InterruptedException e) {                            e.printStackTrace();                            queue.notify();                        }                    }                    queue.poll();                    queue.notify();                    System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素");                }            }        }    }    class Producer extends Thread {        public void run() {            produce();        }        private void produce() {            while(true) {                synchronized (queue) {                    while(queue.size() == queueSize){                        try{                            System.out.println("队列满,等待有空余空间");                            queue.wait();                        }catch (InterruptedException e) {                            e.printStackTrace();                            queue.notify();                        }                    }                    queue.offer(1);                    queue.notify();                    System.out.println("向队列中插入一个元素,队列剩余空间:" + (queueSize - queue.size()));                }            }        }    }}

2 使用Condition实现

package javazongjie;import java.util.PriorityQueue;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Test5 {    private int queueSize = 3;    private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize);    private Lock lock = new ReentrantLock();    private Condition notFull = lock.newCondition();    private Condition notEmpty = lock.newCondition();    public static void main(String[] args) {        Test5 test = new Test5();        Producer producer = test.new Producer();        Consumer consumer = test.new Consumer();        producer.start();        consumer.start();        /**         *  向队列中插入一个元素,队列剩余空间:2            从队列取走一个元素,队列剩余0个元素            队列空,等待数据            //循环输出上述         */    }    class Consumer extends Thread {        public void run() {            consume();        }        private void consume() {            while(true) {                lock.lock();                try{                    while(queue.size() == 0) {                        try{                            System.out.println("队列空,等待数据");                            notEmpty.await();                        }catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                    queue.poll();                    notFull.signal();                    System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素");                }finally {                    lock.unlock();                }            }        }    }    class Producer extends Thread {        public void run() {            produce();        }        private void produce() {            while(true) {                lock.lock();                try{                    while(queue.size() == queueSize){                        try{                            System.out.println("队列满,等待有空余空间");                            notFull.await();                        }catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                    queue.offer(1);                    notEmpty.signal();                    System.out.println("向队列中插入一个元素,队列剩余空间:" + (queueSize - queue.size()));                }finally {                    lock.unlock();                }            }        }    }}
0 0