java线程池的使用,实现大量数据的更新操作

在大量数据更新处理时,单个线程的执行速度过于缓慢,使用多线程可以大幅度的提高执行速度,下面我们来看看具体如何使用java线程池。

第一步,创建一个线程池(单例),用于实例化线程池,记录线程执行相关信息。

package com.qiyongkang.thread.threadpool.test2.common;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class ThreadPool {
    private static ThreadPool instance = null;

    private final ExecutorService executorService;

    private static Long RUNNING_THREAD_COUNT = 0L;

    private static Long startTime = 0L;

    private static long successFutureCount = 0L;

    private static long failFutureCount = 0L;

    private static List<Future<?>> futureList = new ArrayList<Future<?>>();

    private static Map<String, Future<?>> futureMonitorMap = new Hashtable<String, Future<?>>();

    private static Long executeTimeLimit = 72000000L;

    private ThreadPool(int maxSize, long executeTimeLimit) {

        executorService = new ThreadPoolExecutor(maxSize, maxSize, 10L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(100000));
        ThreadPool.executeTimeLimit = executeTimeLimit;
        ThreadPool.startTime = System.currentTimeMillis();
    }

    public static ThreadPool getThreadPool() {
        return instance;
    }

    public synchronized static ThreadPool getInstance(int maxSize, final Logger contextLogger, long executeTimeLimit) {
        if (null == instance) {
            instance = new ThreadPool(maxSize, executeTimeLimit);
        }
        return instance;
    }

    public synchronized static ThreadPool getInstance(int maxSize, final Logger contextLogger) {
        if (null == instance) {
            instance = new ThreadPool(maxSize, executeTimeLimit);
        }
        return instance;
    }

    public synchronized static void startThreadTask() {
        increCount();
    }

    public synchronized static void finishThreadTask() {
        reduceCount();
    }

    private synchronized static void increCount() {
        RUNNING_THREAD_COUNT++;
    }

    private synchronized static void reduceCount() {
        RUNNING_THREAD_COUNT--;
    }

    public static Long getRunningThreadCount() {
        return RUNNING_THREAD_COUNT;
    }

    public int getQueueSize() {
        ThreadPoolExecutor executor = ((ThreadPoolExecutor) executorService);
        return executor.getQueue().size();
    }

    public Future<?> runThread(Runnable runnable) {
        Future<?> futureTask = null;
        try {
            futureTask = executorService.submit(runnable);
            futureList.add(futureTask);
            futureMonitorMap.put(String.valueOf(System.currentTimeMillis()), futureTask);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return futureTask;
    }

    public void shutdown() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }

    public void shutdownNow() {
        if (executorService != null) {
            executorService.shutdownNow();
        }
    }

    public void finishThread() {
        instance.shutdown();
        while (true) {
            Long executeTime = System.currentTimeMillis() - startTime;
            if (ThreadPool.getRunningThreadCount() <= 0 || (executeTime >= executeTimeLimit)) {
                // 已经运行完毕或超时
                ThreadPoolExecutor executor = ((ThreadPoolExecutor) executorService);
                System.out.println("多线程执行完毕,线程任务总数为:" + executor.getTaskCount() + ",线程执行成功数目为:"
                        + executor.getCompletedTaskCount());
                instance.shutdown(); // Disable new tasks from being
                                     // submitted
                try {
                    // Wait a while for existing tasks to terminate
                    if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                        executor.shutdownNow(); // Cancel currently
                                                // executing tasks
                        // Wait a while for tasks to respond to being
                        // cancelled
                        if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                            System.err.println("Pool did not terminated");
                        }
                    }
                } catch (InterruptedException ie) {
                    // (Re-)Cancel if current thread also interrupted
                    executor.shutdownNow();
                }
                break;
            } else {
                operateFutureList();
            }
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized void operateFutureList() {

        for (int i = 0; i < futureList.size(); i++) {
            Future<?> f = futureList.get(i);
            try {
                if (f.isDone()) {
                    successFutureCount++;
                    futureList.remove(i);
                    continue;
                }
                ThreadPoolExecutor executor = ((ThreadPoolExecutor) executorService);
                Long executeTime = System.currentTimeMillis() - startTime;
                if (executeTime >= 36000000 && executor.getQueue().size() <= 0) {
                    f.get(20, TimeUnit.MINUTES);
                }
            } catch (Exception e) {
                failFutureCount++;
                futureList.remove(i);
                try {
                    f.cancel(true);
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }

    }

    public static long getSuccessFutureCount() {
        return successFutureCount;
    }

    public static void setSuccessFutureCount(long successFutureCount) {
        ThreadPool.successFutureCount = successFutureCount;
    }

    public static long getFailFutureCount() {
        return failFutureCount;
    }

    public static void setFailFutureCount(long failFutureCount) {
        ThreadPool.failFutureCount = failFutureCount;
    }

}

第二步,创建一个抽象任务父类,用于将执行线程添加线程池。

package com.qiyongkang.thread.threadpool.test2.common;

import java.util.List;

public abstract class BaseTask<T> {

    protected void executeColl(List<T> coll) throws InterruptedException {

        int threadPerRecord = 1000;

        int times = 0;
        int size = coll.size();
        if (size % threadPerRecord == 0) {
            times = size / threadPerRecord;
        } else {
            times = size / threadPerRecord + 1;
        }

        ThreadPool pool = ThreadPool.getThreadPool();
        for (int i = 0; i < times; i++) {

            int start = i * threadPerRecord;
            int length = (size - (i + 1) * threadPerRecord) >= 0 ? threadPerRecord : (size - i * threadPerRecord);
            List<T> records = null;

            records = coll.subList(start, start + length);

            BaseDealDataService<T> dealDataService = getDealService();

            TaskThread<T> tmTaskThread = new TaskThread<T>(records, dealDataService);

            pool.runThread(tmTaskThread);
        }
    }

    protected abstract BaseDealDataService<T> getDealService();
}

第三步,创建一个抽象处理数据service父类。

package com.qiyongkang.thread.threadpool.test2.common;

import java.util.List;

public abstract class BaseDealDataService<T> {
    public abstract void dealData(List<T> data);
}

第四步,创建单个任务执行线程类。

package com.qiyongkang.thread.threadpool.test2.common;

import java.util.List;


public class TaskThread<T> implements Runnable {

    private BaseDealDataService<T> dealDataService;

    private List<T> dealDatas;

    public TaskThread(List<T> dealDatas, final BaseDealDataService<T> dealDataService) {
        this.dealDatas = dealDatas;
        this.dealDataService = dealDataService;
    }

    @Override
    public void run() {

        try {
            Thread.currentThread().getName();
            System.out.println(Thread.currentThread().getName() + "此线程开始执行");
            ThreadPool.startThreadTask();
            dealDataService.dealData(dealDatas);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ThreadPool.finishThreadTask();
            System.out.println(Thread.currentThread().getName() + "此线程结束执行");
        }
    }

}

第五步,具体的处理数据服务类

package com.qiyongkang.thread.threadpool.test2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.qiyongkang.thread.threadpool.test2.common.BaseDealDataService;
import com.qiyongkang.thread.threadpool.test2.model.User;

public class TestService extends BaseDealDataService<User> {

    @Override
    public void dealData(List<User> data) {
        List<Object[]> list = new ArrayList<Object[]>();
        for (User user : data) {
            Object[] arr = new Object[] {user.getId(), user.getUserName(), user.getAge()};
            list.add(arr);
        }
        String sqlTemplate = "INSERT INTO user1(id, userName, age) VALUES(?, ?, ?)";

        Connection conn = getConn();

        System.out.println("开始批量插入:" + sqlTemplate);
        batchUpdate(sqlTemplate, list, conn);
    }

    public static void batchUpdate(String sqlTemplate, List<Object[]> list, Connection conn) {
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sqlTemplate);
            conn.setAutoCommit(false);
            int size = list.size();
            Object[] o = null;
            for (int i = 0; i < size; i++) {
                o = list.get(i);
                for (int j = 0; j < o.length; j++) {
                    ps.setObject(j + 1, o[j]);
                }
                ps.addBatch();
            }

            ps.executeBatch();
            conn.commit();
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                conn.rollback();
                conn.setAutoCommit(true);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            if(ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static Connection getConn() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "root");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

第六步,具体的任务类,决定调用哪个服务类,以及总体的业务逻辑

package com.qiyongkang.thread.threadpool.test2;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import com.qiyongkang.thread.threadpool.test2.common.BaseDealDataService;
import com.qiyongkang.thread.threadpool.test2.common.BaseTask;
import com.qiyongkang.thread.threadpool.test2.common.ThreadPool;
import com.qiyongkang.thread.threadpool.test2.model.User;

public class TestTask extends BaseTask<User> {

    public void doInternal() {
        //清空数据
        System.out.println("开始清空表数据");
        trucateData();
        System.out.println("结束清空表数据");

        ThreadPool pool = ThreadPool.getInstance(30, Logger.getLogger("TestTask1"));

        System.out.println("开始查询");

        //从数据库查询一个集合
        List<User> userList = new ArrayList<User>();
        for (int i = 0; i < 100000; i++) {
            User user = new User();
            user.setId(i + 1);
            user.setUserName("qiyongkang" + (i + 1));
            user.setAge(i + 1);
            userList.add(user);
        }
        System.out.println("结束查询,总数为:" + userList.size());

        int loop = userList.size() / 10000;

        for (int i = 0; i < loop; i++) {
            List<User> subList = userList.subList(i * 10000, i * 10000 + 10000);
            try {
                executeColl(subList);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //关闭线程池
        pool.finishThread();

    }

    private void trucateData() {
        Connection conn = TestService.getConn();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement("TRUNCATE TABLE user1");
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                ps.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected BaseDealDataService<User> getDealService() {
        return new TestService();
    }

    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        new TestTask().doInternal();
        System.out.println("程序结束");
    }

}
这里,笔者只是讲了讲线程池的使用,具体线程池的原理没有提及,如有什么疑问可以留言!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值