• Object中的线程等待和Condition


    使用wait()notify()的前置条件

    调用wait()和notify()的线程必须是已经获取了synchronized对象锁(注意这里是对象锁不是类锁也就是说被static标记的方法是不行的)的线程。否则将会抛出java.lang.IllegalMonitorStateException

    wait方法会主动让出已经获取到的synchronized锁,使得当前线程阻塞。所以如果线程没有获取到synchronized锁就调用wait()或者notify()就会报错,另外调用wait()和notify()的对象必须要和synchronized

    是同一个对象。

    以下四种代码都是错误的。

    public class Demo2 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo2 demo = new Demo2();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
            t1.start();
        }
    
        public void testa(Object lock) {
            try {
                //错误的
                this.wait();
                System.out.println("aaaaaaaaaaaaaa");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }
    View Code
    public class Demo2 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo2 demo = new Demo2();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
            t1.start();
        }
    
        public void testa(Object lock) {
            try {
                //错误的
                this.notify();
                System.out.println("aaaaaaaaaaaaaa");
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
    View Code
    public class Demo2 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo2 demo = new Demo2();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
            t1.start();
        }
    
        public void testa(Object lock) {
            synchronized (lock) {
                try {
                    //调用wait的对象是this而synchronized当前是Object对象锁
                    this.wait();
                    System.out.println("aaaaaaaaaaaaaa");
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }
        }
    }
    View Code
    public class Demo2 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo2 demo = new Demo2();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
            t1.start();
        }
    
        public void testa(Object lock) {
            synchronized (lock) {
                try {
                    //synchronized使用的是Object锁而调用notify()的是this对象。
                    this.notify();
                    System.out.println("aaaaaaaaaaaaaa");
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
    }
    View Code

    wait()

    调用此方法将当前线程进入阻塞状态,并且让出锁,直到另一个线程调用该对象的notify()方法或notifyAll()方法。

    public class Demo1 {
        public static void main(String[] args) throws Exception {
            Demo1 demo1 = new Demo1();
            Thread t1 = new Thread(() -> {
                demo1.exc();
            });
            t1.start();
    
            Thread t2 = new Thread(() -> {
                demo1.exc2();
            });
            t2.start();
        }
    
        public synchronized void exc() {
            try {
                wait();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            System.out.println("aaa");
        }
    
        public synchronized void exc2() {
            System.out.println("bbb");
        }
    }
    View Code

    以上代码片段t1和t2两个线程都使用的是demo1这个对象的锁。t1执行后获取到了锁,然后调用wait()后自身便处于了阻塞状态,t2线程获得了demo1对象锁并执行结束。

    在这段代码中t1不会只会一直阻塞因为没有线程使用demo1的notify(),t1线程也没有被中断。

    wait(long timeout)

    指定的时间后线程将重新恢复就绪状态,拥有争夺锁的权力。参数单位为毫秒。

    public class Demo1 {
        public static void main(String[] args) throws Exception {
            Demo1 demo1 = new Demo1();
            Thread t1 = new Thread(() -> {
                demo1.exc();
            });
            t1.start();
    
            Thread t2 = new Thread(() -> {
                demo1.exc2();
            });
            t2.start();
        }
    
        public synchronized void exc() {
            try {
                wait(3000);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            System.out.println("aaa");
        }
    
        public synchronized void exc2() {
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
    
            System.out.println("bbb");
        }
    }
    View Code

    以上代码片段t1线程执行后会阻塞直到3秒后将重新恢复就绪状态,但此时锁被t2获取正在执行,直到t2执行结束后释放锁,t1继续执行。

    wait(long timeout,int nanos)

    这个重载方法除了毫秒外还允许传递一个int类型的纳秒值,取值范围是0-999999。纳秒和毫秒的换算是1毫秒=1000000纳秒。也就是说第二个参数最多接近于1毫秒。

    public class Demo1 {
        public static void main(String[] args) throws Exception {
            Demo1 demo1 = new Demo1();
            Thread t1 = new Thread(() -> {
                demo1.exc();
            });
            t1.start();
    
            Thread t2 = new Thread(() -> {
                demo1.exc2();
            });
            //t2.start();
        }
    
        public synchronized void exc() {
            try {
                System.out.println(System.currentTimeMillis());
                wait(3000,999999);
                System.out.println(System.currentTimeMillis());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            System.out.println("aaa");
        }
    
        public synchronized void exc2() {
            System.out.println("bbb");
        }
    }
    View Code

    以上代码片段只执行了t1,t1线程在阻塞前和阻塞后的时间差大概为3016毫秒。

    wait释放的哪个锁?

    public class Demo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo1 demo = new Demo1();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
    
            Thread t2 = new Thread(() -> {
                demo.testb(lock);
            });
    
            t1.start();
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
    
            t2.start();
    
        }
    
        public synchronized void testa(Object lock) {
            System.out.println("aaaaaaaaaaaaaa1");
            synchronized (lock) {
                System.out.println("aaaaaaaaaaaaaa2");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public synchronized void testb(Object lock) {
            System.out.println("bbbbbbbbbbbbbbbbbbb1");
            synchronized (lock) {
                System.out.println("bbbbbbbbbbbbbbbbbbb2");
            }
        }
    }
    View Code

    以上代码片段testa()和testb()两个方法上有synchronized方法内部还有synchronized (lock){}。在main()中线程1执行a方法线程2执行b方法。最终的执行结果是:

    aaaaaaaaaaaaaa1
    aaaaaaaaaaaaaa2
    bbbbbbbbbbbbbbbbbbb1

    出现这个结果的原因是线程1执行a方法时先拿到this锁也就是Demo对象的锁,又拿到了lock这个锁(也就是Object这个对象的锁)然后wait()执行后释放了this锁,为什么释放的是this锁?因为wait()默认使用的对象是this。也就是this.wait();

    线程2执行b方法获取了this锁,但是无法拿到lock对象锁,所以进不去代码块。

    public class Demo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo1 demo = new Demo1();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
    
            Thread t2 = new Thread(() -> {
                demo.testb(lock);
            });
    
            t1.start();
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
    
            t2.start();
    
        }
    
        public synchronized void testa(Object lock) {
            System.out.println("aaaaaaaaaaaaaa1");
            synchronized (lock) {
                System.out.println("aaaaaaaaaaaaaa2");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public synchronized void testb(Object lock) {
            System.out.println("bbbbbbbbbbbbbbbbbbb1");
            synchronized (lock) {
                System.out.println("bbbbbbbbbbbbbbbbbbb2");
            }
        }
    }
    View Code

    将代码稍稍修改,wait()由lock对象调用。执行结果是:

    aaaaaaaaaaaaaa1
    aaaaaaaaaaaaaa2

    结果不出意料,lock.wait()释放了lock这个对象锁。线程2执行b方法拿不到this锁第一层都进不去。

    public class Demo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo1 demo = new Demo1();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
    
            Thread t2 = new Thread(() -> {
                demo.testb(lock);
            });
    
            t1.start();
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
    
            t2.start();
    
        }
    
        public synchronized void testa(Object lock) {
            System.out.println("aaaaaaaaaaaaaa1");
            synchronized (this) {
                System.out.println("aaaaaaaaaaaaaa2");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public synchronized void testb(Object lock) {
            System.out.println("bbbbbbbbbbbbbbbbbbb1");
            synchronized (lock) {
                System.out.println("bbbbbbbbbbbbbbbbbbb2");
            }
        }
    }
    View Code

    将a方法中synchronized代码块的锁修改为this。此时a方法中的两个锁都是this。执行wait()释放this锁。线程2执行b方法可以获取this锁,同时lock对象锁占用也可以获取所以打印结果是:

    aaaaaaaaaaaaaa1
    aaaaaaaaaaaaaa2
    bbbbbbbbbbbbbbbbbbb1
    bbbbbbbbbbbbbbbbbbb2

    notify()

    唤醒正在等待对象监控的单个线程。

    public class Demo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo1 demo = new Demo1();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
    
            Thread t2 = new Thread(() -> {
                demo.testb(lock);
            });
    
            Thread t3 = new Thread(() -> {
                demo.testc(lock);
            });
    
            t2.start();
            t1.start();
            try {
                Thread.sleep(1000);
            }catch (Exception e) {
            }    
            t3.start();
        }
    
        public synchronized void testa(Object lock) {
            try {
                this.wait();
                System.out.println("aaaaaaaaaaaaaa");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    
        public synchronized void testb(Object lock) {
            try {
                this.wait();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    
        public void testc(Object lock) {
            synchronized (this) {
                try {
                    this.notify();
                } catch (Exception e) {
                    System.out.println(e);
                }
    
            }
    
        }
    }
    View Code

    以上代码片段线程1和线程2执行a,b方法。而a,b方法都调用了this.wait()也就是说t1和t2线程都是被this对象锁阻塞了。线程3调用this.notify()会唤醒t1,t2中的一个阻塞线程。

    public class Demo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo1 demo = new Demo1();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
    
            Thread t2 = new Thread(() -> {
                demo.testb(lock);
            });
    
            Thread t3 = new Thread(() -> {
                demo.testc(lock);
            });
    
            t2.start();
            t1.start();
            try {
                Thread.sleep(1000);
            }catch (Exception e) {
            }    
            t3.start();
        }
    
        public synchronized void testa(Object lock) {
            try {
                this.wait();
                System.out.println("aaaaaaaaaaaaaa");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    
        public synchronized void testb(Object lock) {
            try {
                this.wait();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    
        public void testc(Object lock) {
            synchronized (lock) {
                try {
                    lock.notify();
                } catch (Exception e) {
                    System.out.println(e);
                }
    
            }
    
        }
    }
    View Code

    将c方法中的锁更改为lock对象,notify()方法也由lock对象调用则t1,t2两个线程都不会被唤醒。因为notify()唤醒的线程只能是被和自身同一个对象锁阻塞的线程。

    另外如果c方法的synchronized是this锁而调用notify()的是其他对象则也会报错。

    notifyAll()

    唤醒正在等待对象监控的所有线程。

    public class Demo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Demo1 demo = new Demo1();
    
            Thread t1 = new Thread(() -> {
                demo.testa(lock);
            });
    
            Thread t2 = new Thread(() -> {
                demo.testb(lock);
            });
    
            Thread t3 = new Thread(() -> {
                demo.testc(lock);
            });
    
            t2.start();
            t1.start();
            try {
                Thread.sleep(1000);
            }catch (Exception e) {
            }    
            t3.start();
        }
    
        public synchronized void testa(Object lock) {
            try {
                this.wait();
                System.out.println("aaaaaaaaaaaaaa");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    
        public synchronized void testb(Object lock) {
            try {
                this.wait();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    
        public void testc(Object lock) {
            synchronized (this) {
                try {
                    this.notifyAll();
                } catch (Exception e) {
                    System.out.println(e);
                }
    
            }
    
        }
    }
    View Code

    以上代码将notify()更换成了notifyAll()则t1,和t2线程都会被唤醒。

    Condition

    condition接口它的功能其实和Object中的wait()notify()方法的作用是一样的。wait()使线程进入阻塞状态notify()解除线程的阻塞状态它们要配合synchronized使用。

    也就是说只有被synchronized锁住的代码块内才可以使用wait()和notify()。

    condition接口提供了await();使用线程进入阻塞状态sigal()解除线程阻塞状态。则是配合Lock接口使用的。

    Lock.newCondition()方法获取一个Condition接口的实现类。

    await()signal()的前置条件

    await()和signal()必须要在lock()方法后,并且调用await()signal()的Condition对象必须和lock()方法是同一组内的。也就是说一个Lock对象要和Condition对象是成对使用

    的。这和wait()notify()方法必须和synchronized锁是同一个对象锁是一样的。

    以下四种写法都是错误的。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(()->{
                demo.a();
            });
            t1.start();
        }
    
        public void a() {
            try {
                condition.await();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
    View Code
    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(()->{
                demo.a();
            });
            t1.start();
        }
    
        public void a() {
            try {
                condition.signal();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
    View Code
    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        
        ReentrantLock lock2 = new ReentrantLock();
        Condition condition2 = lock2.newCondition();
        
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(()->{
                demo.a();
            });
            t1.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition2.await();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
    View Code
    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        
        ReentrantLock lock2 = new ReentrantLock();
        Condition condition2 = lock2.newCondition();
        
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(()->{
                demo.a();
            });
            t1.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition2.signal();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
    View Code

    await()

    使当前线程阻塞直到中断或被signal()方法唤醒。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            t1.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t2.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.await();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上代码执行结果是t1线程被阻塞不会执行输出,t2线程会正常结束。t1线程执行a()方法后获取lock锁然后await()会将当前线程阻塞并且释放lock锁。t2线程获取锁输出结果后释放锁,但t1线程始终无人唤醒。

    await(timeout,TimeUnit)

    这个重载方法给除了一个等待时间和时间单位。如果在指定时间结束后线程没有被signal()方法唤醒也没有中断则会自动被唤醒。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            t1.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t2.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.await(3,TimeUnit.SECONDS);
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上方法t1线程阻塞后释放lock锁,t2线程获取锁在执行完毕后释放lock锁。t1线程在3秒后自动唤醒然后获取lock锁执行代码。

    awaitNanos(timeout)

    这个重载方法以纳秒为单位的时间单位。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            t1.start();
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t2.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.awaitNanos(3000000000L);
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上代码片段3000000000L纳秒也就是3秒它的执行效果和condition.await(3,TimeUnit.SECONDS)是相同的。

    awaitUntil(Date)

    这个重载方法接收一个Date时间,表示在指定的时间到达后自动唤醒线程。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            t1.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t2.start();
        }
    
        public void a() {
            try {
                lock.lock();
                SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date parse = sm.parse("2021-01-23 22:35:00");
                condition.awaitUntil(parse);
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上代码t2线程会在时间到达后获取锁并执行完毕。

    awaitUninterruptibly()

    以上4个使线程阻塞的方法如果在阻塞过程中线程被调用interrupt()则会接收到一个InterruptedException异常。而awaitUninterruptibly()阻塞方法被中断则不会接收到异常。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            t1.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t2.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t1.interrupt();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.await();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code
    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            t1.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t2.start();
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t1.interrupt();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.awaitUninterruptibly();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                System.out.println("bbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上两个代码片段第一个会接收到InterruptedException异常第二个则不会。

    signal

    signal()唤醒一个被当前lock锁阻塞的线程。它从await()阻塞队列中获取阻塞时间最长的线程将其唤醒。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            Thread t3 = new Thread(() -> {
                demo.c();
            });
            t2.start();
            t1.start();
            
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t3.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.await();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                condition.await();
                System.out.println("bbbbbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void c() {
            try {
                lock.lock();
                System.out.println("ccccccccccc");
                condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上代码片段t3线程执行后会释放阻塞队列中阻塞时间最长的线程也就是t2线程,t1线程不会被唤醒。

    signalAll

    signal()唤醒所有被当前lock锁阻塞的线程。

    public class Demo2 {
    
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            Demo2 demo = new Demo2();
            Thread t1 = new Thread(() -> {
                demo.a();
            });
            Thread t2 = new Thread(() -> {
                demo.b();
            });
            Thread t3 = new Thread(() -> {
                demo.c();
            });
            t2.start();
            t1.start();
            
            try {
                Thread.sleep(1000 * 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            t3.start();
        }
    
        public void a() {
            try {
                lock.lock();
                condition.await();
                System.out.println("aaaaaaaaaaaa");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void b() {
            try {
                lock.lock();
                condition.await();
                System.out.println("bbbbbbbbbbbbbbbbb");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void c() {
            try {
                lock.lock();
                System.out.println("ccccccccccc");
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    View Code

    以上代码t3线程执行后会将t2,t1线程全部唤醒。

    模拟生产者消费着案例

    synchronized,wait,notifyAll实现

    package com.datang.bingxiang;
    
    
    public class Demo3 {
    
        int count = 0;
        int no = 0;
    
        public void produce() {
            synchronized (this) {
                while (count != 0) {
                    try {
                        notifyAll();
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                count++;
                no++;
                String name = Thread.currentThread().getName();
                System.out.println(name + "正在生产" + no);
            }
        }
    
        public void consumer() {
            synchronized (this) {
                while (count == 0) {
                    try {
                        notifyAll();
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                count--;
                String name = Thread.currentThread().getName();
                System.out.println(name + "正在消费" + no);
            }
        }
    
        public static void main(String[] args) {
            Demo3 demo = new Demo3();
            Thread t1 = new Thread(() -> {
                while (true) {
                    demo.produce();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread t2 = new Thread(() -> {
                while (true) {
                    demo.produce();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread t3 = new Thread(() -> {
                while (true) {
                    demo.consumer();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread t4 = new Thread(() -> {
                while (true) {
                    demo.consumer();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    View Code

    ReentrantLock,Condition实现

    package com.datang.bingxiang;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Demo4 {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        int count = 0;
        int no = 0;
    
        public void produce() {
            try {
                lock.lock();
                while (count != 0) {
                    try {
                        condition.signalAll();
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                count++;
                no++;
                String name = Thread.currentThread().getName();
                System.out.println(name + "正在生产" + no);
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
    
        }
    
        public void consumer() {
            try {
                lock.lock();
                while (count == 0) {
                    try {
                        condition.signalAll();
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                count--;
                String name = Thread.currentThread().getName();
                System.out.println(name + "正在消费" + no);
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
    
        public static void main(String[] args) {
            Demo4 demo = new Demo4();
            Thread t1 = new Thread(() -> {
                while (true) {
                    demo.produce();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread t2 = new Thread(() -> {
                while (true) {
                    demo.produce();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread t3 = new Thread(() -> {
                while (true) {
                    demo.consumer();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread t4 = new Thread(() -> {
                while (true) {
                    demo.consumer();
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    View Code
  • 相关阅读:
    UIButton添加倒计时
    AFNetworking+Python+Flask+pyOpenSSL构建iOS HTTPS客户端&服务器端
    js脚本都可以放在哪些地方
    js实现整数转化为小数
    JavaBean自动生成get和set方法
    servlet与Javabean之间的区别
    搞不懂SSH与JAVA+Servlet+javabean有什么关系
    启动 Eclipse 弹出“Failed to load the JNI shared library jvm.dll”的解决方法!
    win8安装sql2008及设置登陆名问题
    jdbc的配置及jdbc连接常用数据库(mysql、sqlserver、Oracle)
  • 原文地址:https://www.cnblogs.com/zumengjie/p/14312549.html
Copyright © 2020-2023  润新知