美文网首页
八、Java高级特性(wait,notify/notifyAll

八、Java高级特性(wait,notify/notifyAll

作者: 大虾啊啊啊 | 来源:发表于2021-05-28 09:19 被阅读0次

    一、前言

    今天我们通过wait,notify/notifyAll的知识实现一个等待超时的数据库连接池

    二、代码

    1、自定义一个数据库连接类

    package com.it.test.thread;
    
    public class MyConnction {
        public void createStatement() {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    
        public void commit() {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    }
    
    

    2、创建连接池

    package com.it.test.thread;
    
    import java.util.LinkedList;
    
    public class ConnectionPool {
        /**
         * 数据库连接池
         */
        LinkedList<MyConnction> pools = new LinkedList<>();
        /**
         * 默认1S的超时时间
         */
        private static final int TIME = 100;
    
    
        /**
         * 初始化连接池的
         *
         * @param size
         */
        public ConnectionPool(int size) {
            for (int i = 0; i < size; i++) {
                pools.addLast(new MyConnction());
            }
        }
    
        /**
         * 从连接池中获取连接
         *
         * @return
         */
        public MyConnction getPool() {
            synchronized (pools) {
                long outTime = System.currentTimeMillis() + TIME;
                /**
                 * 如果连接是空的,并且超时时间未结束,则等待休眠
                 */
                while (pools.isEmpty() && (outTime - System.currentTimeMillis()) > 0) {
                    try {
                        //每次被唤醒之后(有可能被其他线程唤醒)
                        //根据计算剩余的超时时间继续休眠
                        pools.wait(outTime - System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (!pools.isEmpty()) {
                    return pools.removeFirst();
                } else {
                    return null;
                }
    
    
            }
    
    
        }
    
        /**
         * 释放连接
         */
        public void releasePool(MyConnction connection) {
            if (connection != null) {
                synchronized (pools) {
                    pools.addLast(connection);
                    pools.notifyAll();
    
                }
    
            }
    
    
        }
    
    
    }
    
    

    3、编写测试类

    package com.it.test.thread.pool;
    
    
    import com.it.test.thread.ConnectionPool;
    import com.it.test.thread.MyConnction;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     *类说明:
     */
    public class DBPoolTest {
        static ConnectionPool pool  = new ConnectionPool(10);
        // 控制器:控制main线程将会等待所有Woker结束后才能继续执行
        static CountDownLatch end;
    
        public static void main(String[] args) throws Exception {
            // 线程数量
            int threadCount = 50;
            end = new CountDownLatch(threadCount);
            int count = 20;//每个线程的操作次数
            AtomicInteger got = new AtomicInteger();//计数器:统计可以拿到连接的线程
            AtomicInteger notGot = new AtomicInteger();//计数器:统计没有拿到连接的线程
            for (int i = 0; i < threadCount; i++) {
                Thread thread = new Thread(new Worker(count, got, notGot), 
                        "worker_"+i);
                thread.start();
            }
            end.await();// main线程在此处等待
            System.out.println("总共尝试了: " + (threadCount * count));
            System.out.println("拿到连接的次数:  " + got);
            System.out.println("没能连接的次数: " + notGot);
        }
    
        static class Worker implements Runnable {
            int           count;
            AtomicInteger got;
            AtomicInteger notGot;
    
            public Worker(int count, AtomicInteger got,
                                   AtomicInteger notGot) {
                this.count = count;
                this.got = got;
                this.notGot = notGot;
            }
    
            public void run() {
                while (count > 0) {
                    try {
                        // 从线程池中获取连接,如果1000ms内无法获取到,将会返回null
                        // 分别统计连接获取的数量got和未获取到的数量notGot
                        MyConnction connection = pool.getPool();
                        if (connection != null)
                        {
                            try {
                                connection.createStatement();
    //                            PreparedStatement preparedStatement
    //                                    = connection.prepareStatement("");
    //                            preparedStatement.execute();
                                connection.commit();
                            } finally {
                                pool.releasePool(connection);
                                got.incrementAndGet();
                            }
                        } else {
                            notGot.incrementAndGet();
                            System.out.println(Thread.currentThread().getName()
                                    +"等待超时!");
                        }
                    } catch (Exception ex) {
                    } finally {
                        count--;
                    }
                }
                end.countDown();
            }
        }
    }
    
    
    总共尝试了: 1000
    拿到连接的次数:  652
    没能连接的次数: 348
    
    

    总结

    wait,notify/notifyAll属于Object下的方法,使用的时候必须在同步代码块内,也就是必须在synchronized 关键字修饰的代码内。

    • 调用wait方法的时候,会释放当前的锁,进入等待状态
    • 调用notify和notifyAll方法,会随机唤醒或者全部唤醒一个线程,尽量使用notifyAll。因为notifyAll唤醒的是全部线程。当之前进入wait状态的线程收到notify唤醒通知之后,重新竞争锁,如果竞争到了,那么就在调用wait方法的地方继续往下执行。
      -调用wait方法会释放当前锁,而调用notify和notifyAll不会释放当前锁,只有执行完notify部分的代码完,才会释放锁,所以通常我们把调用notify方法方在最后。

    相关文章

      网友评论

          本文标题:八、Java高级特性(wait,notify/notifyAll

          本文链接:https://www.haomeiwen.com/subject/jnjrsltx.html