在大量数据更新处理时,单个线程的执行速度过于缓慢,使用多线程可以大幅度的提高执行速度,下面我们来看看具体如何使用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 = 0 L;
private static Long startTime = 0 L;
private static long successFutureCount = 0 L;
private static long failFutureCount = 0 L;
private static List> futureList = new ArrayList>();
private static Map> futureMonitorMap = new Hashtable>();
private static Long executeTimeLimit = 72000000 L;
private ThreadPool (int maxSize, long executeTimeLimit) {
executorService = new ThreadPoolExecutor(maxSize, maxSize, 10 L, TimeUnit.SECONDS,
new ArrayBlockingQueue(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 {
protected void executeColl (List 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 records = null ;
records = coll.subList(start, start + length);
BaseDealDataService dealDataService = getDealService();
TaskThread tmTaskThread = new TaskThread(records, dealDataService);
pool.runThread(tmTaskThread);
}
}
protected abstract BaseDealDataService getDealService ();
}
第三步,创建一个抽象处理数据service父类。
package com.qiyongkang.thread.threadpool.test2.common;
import java.util.List;
public abstract class BaseDealDataService {
public abstract void dealData (List data);
}
第四步,创建单个任务执行线程类。
package com.qiyongkang.thread.threadpool.test2.common;
import java.util.List ;
public class TaskThread <T > implements Runnable {
private BaseDealDataService dealDataService;
private List dealDatas;
public TaskThread(List dealDatas, final BaseDealDataService 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 .test 2
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 .test 2.common .BaseDealDataService
import com .qiyongkang .thread .threadpool .test 2.model .User
public class TestService extends BaseDealDataService {
@Override
public void dealData(List data) {
List list = new ArrayList()
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 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 .test 2
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 .test 2.common .BaseDealDataService
import com .qiyongkang .thread .threadpool .test 2.common .BaseTask
import com .qiyongkang .thread .threadpool .test 2.common .ThreadPool
import com .qiyongkang .thread .threadpool .test 2.model .User
public class TestTask extends BaseTask {
public void doInternal() {
//清空数据
System.out .println ("开始清空表数据" )
trucateData()
System.out .println ("结束清空表数据" )
ThreadPool pool = ThreadPool.getInstance (30 , Logger.getLogger ("TestTask1" ))
System.out .println ("开始查询" )
//从数据库查询一个集合
List userList = new ArrayList()
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 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 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 ("程序结束" )
}
}
这里,笔者只是讲了讲线程池的使用,具体线程池的原理没有提及,如有什么疑问可以留言!