在大量数据更新处理时,单个线程的执行速度过于缓慢,使用多线程可以大幅度的提高执行速度,下面我们来看看具体如何使用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();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminated");
}
}
} catch (InterruptedException ie) {
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
o = list.get(i)
for (int j = 0
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
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
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("程序结束")
}
}
这里,笔者只是讲了讲线程池的使用,具体线程池的原理没有提及,如有什么疑问可以留言!