使用ThreadPool来解决大量数据处理请求

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29956725/article/details/88666907
package book.thread.pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;


public class JDBCTools {
    private static final AtomicInteger nextId = new AtomicInteger(0);
    public static String HOST = "localhost";
    public static String PORT = "3306";
    public static String DATABASE_NAME = "jpress";
    public static String USER_NAME = "root";
    public static String PASSWORD = "123456";

    public static void main(String[] args) throws Exception {

        executeSql();
        executeSqlByThreadPool(getRunnable());

    }

    /**
     * 默认执行,这种方式如果,Thread链接数设置太多,大于200左右,一般就会挂掉,即使设置了mysql的最大链接数
     *  show variables like '%max_connections%';
        set GLOBAL max_connections = 16384;
     */
    private static void executeSql() {
        for(int i= 0 ;i< 100; i++) {
            Thread thread = new Thread(getRunnable());
            thread.start();
        }
    }

    /**
     *  使用线程池的方式来解决此问题,  声明100个线程,1000个 insert的任务,然后每次执行100个任务,这样依次执行
     *
     */
    private static void executeSqlByThreadPool(Runnable runnable) {
        ExecutorService pool = Executors.newFixedThreadPool(100);
        for (int i = 0; i < 100; i++) {
            // 可以执行Runnable对象或者Callable对象代表的线程
            pool.submit(runnable);
            pool.submit(runnable);
            pool.submit(runnable);
            pool.submit(runnable);
            pool.submit(runnable);

            pool.submit(runnable);
            pool.submit(runnable);
            pool.submit(runnable);
            pool.submit(runnable);
            pool.submit(runnable);
        }
    }

    /**
     * 策略3,分库分表策略
     * @return
     */


    private static Runnable getRunnable() {
        return ()->{
                try {
                    System.out.println(Thread.currentThread().getName() +"sql session");
                 //   JDBCTools.query("select * from Test ");
                    JDBCTools.execute("insert Test(name) VALUE ('"+  nextId.getAndIncrement() + "')");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
    }

    /**
     * 获取数据库连接
     * @return 数据库连接
     */
    public static Connection getConn() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("成功加载驱动");

        String url = "jdbc:mysql://" + HOST + ":" + PORT + "/" + DATABASE_NAME + "?user=" + USER_NAME + "&password=" + PASSWORD + "&testOnBorrow=true ";
        System.out.println(url);


        Connection connection = DriverManager.getConnection(url);
        System.out.println("成功获取连接");
        return connection;
    }

    /**
     * 关闭资源
     */
    public static void closeResource(Connection conn, Statement st, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                // TODO 处理异常
                e.printStackTrace();
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {
                // TODO 处理异常
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO 处理异常
                e.printStackTrace();
            }
        }
        System.out.println("成功关闭资源");
    }

    /**
     * 查询SQL
     * @param sql 查询语句
     * @return 数据集合
     * @throws SQLException
     */
    public static List<Map<String, String>> query(String sql) throws Exception {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        List<Map<String, String>> resultList = null;

        try {
            connection = JDBCTools.getConn();

            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);
            System.out.println("SQL : " + sql);

            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            int columnCount = resultSetMetaData.getColumnCount();
            String[] columnNames = new String[columnCount + 1];
            for (int i = 1; i <= columnCount; i++) {
                columnNames[i] = resultSetMetaData.getColumnName(i);
            }

            resultList = new ArrayList<Map<String, String>>();

            resultSet.beforeFirst();
            while (resultSet.next()) {
                Map<String, String> resultMap = new HashMap<String, String>();
                for (int i = 1; i <= columnCount; i++) {
                    resultMap.put(columnNames[i], resultSet.getString(i));
                }

                resultList.add(resultMap);
            }
            System.out.println("成功查询数据库,查得数据:" + resultList);
        } catch(Throwable t) {
            // TODO 处理异常
            t.printStackTrace();
        } finally {
            JDBCTools.closeResource(connection, statement, resultSet);
        }

        return resultList;
    }

    /**
     * 执行SQL
     * @param sql 执行的SQL
     * @return 操作条数
     */
    public static int execute(String sql) throws Exception {

        Thread.sleep(2000);

        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        int num = 0;

        try {
            connection = JDBCTools.getConn();

            statement = connection.createStatement();
            num = statement.executeUpdate(sql);
            System.out.println("SQL : " + sql);
            System.out.println("成功操作数据库,影响条数:" + num);

            // 模拟异常,用于测试事务
            /*
            if (1 == 1) {
                throw new RuntimeException();
            }
            */

        } catch(Exception e) {
            // 处理异常:回滚事务后抛出异常
            e.printStackTrace();
            // connection.rollback();
            System.out.println("事务回滚");
            throw e;
        } finally {
            JDBCTools.closeResource(connection, statement, resultSet);
        }

        return num;
    }


}

判断线程池结束的方法为:   exe.shutdown();该方法在加入线程队列的线程执行完之前不会执行

  exe.isTerminated();当shutdown()或者shutdownNow()执行了之后才会执行,并返回true

public class Test {  
  
    public static void main(String args[]) throws InterruptedException {  
        ExecutorService exe = Executors.newFixedThreadPool(50);  
        for (int i = 1; i <= 5; i++) {  
            exe.execute(new SubThread(i));  
        }  
        exe.shutdown();  
        while (true) {  
            if (exe.isTerminated()) {  
                System.out.println("结束了!");  
                break;  
            }  
            Thread.sleep(200);  
        }  
    }  

}  

一般情况下牵扯到第三方的jar包时,不要用Thread.activeCount(),因为一般默认会等于2,但是使用第三方jar包时,并不一定就是2了,如下所示,当我们使用okHttp.jar进行请求时,则出现了以下情况,共有四个,此时,则会和我们的要求不符合

activeCount-->main
activeCount-->Monitor Ctrl-Break
activeCount-->OkHttp ConnectionPool
activeCount-->Okio Watchdog
 

 

猜你喜欢

转载自blog.csdn.net/qq_29956725/article/details/88666907