近日在学习java并发编程方面的知识,在参考了并发编程网的相关文章并发实战题(一)及方腾飞的并发编程艺术后,实现一个简单的限流线程任务提交工具。
package com.jerry.common;
import com.jerry.common.task.MyTask;
import com.jerry.common.task.RunThread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author Jerry
* @created 2017年3月29日 下午2:08:22
* @overview
*/
public class ExecutorQueueStore {
private volatile static ExecutorQueueStore INSTANCE;
final static int threadPoolLimitNum = 100;
final static int semaphoreLimitNum = 10;
final Semaphore semaphore = new Semaphore(semaphoreLimitNum);
final ScheduledExecutorService scheduled = Executors
.newSingleThreadScheduledExecutor();
// final ExecutorService executor = Executors.newFixedThreadPool(limitNum);
final ExecutorService executor = new ThreadPoolExecutor(threadPoolLimitNum,
threadPoolLimitNum, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(threadPoolLimitNum), new MyExecutionHandler());
public static ExecutorQueueStore getInstence() {
if (null == INSTANCE) {
synchronized (ExecutorQueueStore.class) {
if (null == INSTANCE) {
INSTANCE = new ExecutorQueueStore();
INSTANCE.runSchedule();
}
}
}
return INSTANCE;
}
private void runSchedule() {
scheduled.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
semaphore.release(semaphoreLimitNum);
}
}, 2000, 2000, TimeUnit.MILLISECONDS);
}
public String submit(Callable<String> task) {
try {
semaphore.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Future<String> future = executor.submit(task);
// TODO 此处可以做些其他的事
String result;
try {
result = future.get();
} catch (InterruptedException e) {
System.out.println("Error:" + e.getMessage());
return "FAIL";
} catch (ExecutionException e) {
System.out.println("Error:" + e.getMessage());
return "FAIL";
}
return result;
}
public static void destroy() {
if (null != INSTANCE) {
INSTANCE.executor.shutdown();
while (!INSTANCE.executor.isTerminated()) {
try {
INSTANCE.executor.awaitTermination(5000,
TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println("executor shutdown fail, errorMsg:"
+ e.getMessage());
}
INSTANCE.executor.shutdown();
}
INSTANCE.scheduled.shutdown();
while (!INSTANCE.scheduled.isTerminated()) {
try {
INSTANCE.scheduled.awaitTermination(3000,
TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println("scheduled shutdown fail, errorMsg:"
+ e.getMessage());
}
INSTANCE.scheduled.shutdown();
}
INSTANCE = null;
}
}
public static void main(String[] args) {
MyTask task;
for (int i = 0; i < 1000; i++) {
task = new MyTask("ThreadNo" + i);
RunThread rt = new RunThread(task);
rt.start();
}
// System.out.println("线程池关闭");
// ExecutorQueueStore.destroy();
}
}
package com.jerry.common;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
/**
*
* @author Jerry
* @created 2017年3月30日 下午4:22:39
* @overview
*/
public class MyExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("队列已满,开始执行异常处理流程,听张震讲鬼故事");
// log
// db
System.out.println("异常处理流程结束");
}
}
package com.jerry.common.task;
import java.util.concurrent.Callable;
/**
*
* @author Jerry
* @created 2017年3月24日 下午5:13:32
* @overview
*/
public class MyTask implements Callable<String> {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
String no = name.substring(name.indexOf('o') + 1);
int num = Integer.parseInt(no);
if (num % 10 == 0) {
return "FAIL," + name;
}
return name;
}
public MyTask(String name) {
super();
this.name = name;
}
}
package com.jerry.common.task;
import com.jerry.common.ExecutorQueueStore;
/**
*
* @author Jerry
* @created 2017年3月30日 下午5:06:45
* @overview
*/
public class RunThread extends Thread{
private MyTask mytask;
public RunThread(MyTask mytask) {
super();
this.mytask = mytask;
}
public void run(){
String result = ExecutorQueueStore.getInstence().submit(mytask);
if (result.contains("FAIL")) {
System.out.println("任务执行失败");
System.out.println("失败原因:" + result);
} else {
System.out.println("执行成功");
System.out.println("任务名称:" + result);
}
}
}
目前结束线程时有一些问题,正在思考.....