问题描述
- java线程池当其中一个线程算出结果,终止全部线程
-
业务逻辑:一个大型社区,每一秒有上千人在提交留言,提交的留言将经过,上万条的正则表达式的过滤,没有匹配任何规则的,才保存到系统,否则提示用户,您录入的内容不合法。
我是这样想的,把这上万条正则表达式,拆分成2000条一组,开一个5个线程的线程池,每个线程将负责其中2000个规则的匹配。
每条留言提交时,将由这5个线程,去判断是否有匹配的规则,如果其中一个线程匹配到了规则,将结束其他4个线程的任务,返回给用户结果。
请问这种要怎么实现。。
是不是用到
ExecutorService exec = Executors.newFixedThreadPool(5);
java.util.concurrent.Future;
解决方案
可以类似下面这样
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
public class TestThread {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
String c = "评论1";
TxtClass tx = new TxtClass(c);
CountDownLatch cdLatch = new CountDownLatch(5);
Thread tr = new CRThread(1,tx,cdLatch);//1表示第一个
Thread tr2 = new CRThread(2,tx,cdLatch);
Thread tr3 = new CRThread(3,tx,cdLatch);
Thread tr4 = new CRThread(4,tx,cdLatch);
Thread tr5 = new CRThread(5,tx,cdLatch);
tr.start();
tr2.start();
tr3.start();
tr4.start();
tr5.start();
cdLatch.await();
System.out.println("都执行完了,结果["+tx.isFind() + "]");
}
}
class TxtClass{
private String c = "";
private boolean isFind = false;
public TxtClass(String c){
this.c = c;
}
public boolean isFind() {
return isFind;
}
public void setFind(boolean isFind) {
this.isFind = isFind;
}
public String getC() {
return c;
}
}
class RegClass{//校验规则
private static RegClass rc = new RegClass();
public static RegClass getInstance(){
return rc;
}
private ArrayList<String> list = new ArrayList();
public RegClass(){//初始化规则
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("s");
list.add("1");
list.add("评");
list.add("a");
list.add("b");
list.add("r");
}
public boolean isContains(int index,String c){
if(list.size()>index){
return c.indexOf(list.get(index))>=0;
}else{
return false;
}
}
}
class CRThread extends Thread{
private int startNum = 0;
private TxtClass txtClass;//留言内容
private CountDownLatch cdLatch;
private int oneLength = 2000;//一个线程校验的长度
public CRThread(int i,TxtClass txtClass,CountDownLatch cdLatch){
super();
this.startNum = i;
this.txtClass = txtClass;
this.cdLatch = cdLatch;
}
@Override
public void run() {
boolean f = false;
int nums = 0;
for(int i=0;i<oneLength;i++){
nums = (startNum-1)*oneLength+i;
System.out.println("thread-"+startNum+"-["+nums+"]");
f=RegClass.getInstance().isContains(nums, txtClass.getC());
if(f){
txtClass.setFind(true);
}
if(txtClass.isFind()){
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread-"+startNum+"-结束["+nums+"]");
this.cdLatch.countDown();
}
}
解决方案二:
谢谢楼上两位的回复
但是每次都 Thread tr = new CRThread(1,tx,cdLatch); 这样新开线程,效率会不会低一点呢
其实我是想用一个线程池,专门处理这个内容检查,一个评论扔到这个池里面,池经过多线程匹配计算,抛出结果
解决方案三:
"每一秒有上千人在提交留言"
既然同时要进行这么多的检查,1个留言用5个线程各自处理2000个匹配,不如这5个线程取处理5个留言的10000个匹配简单(之间跳出自己的循环即可)。
反正两个方案都是平均1个留言做5000次匹配。
解决方案四:
cdLatch.await();
System.out.println("都执行完了,结果["+tx.isFind() + "]");
这样一await,是不是全部线程都要执行完,才会给结果的?
如果其中一个线程已经算出结果了,其他几个会自动听下来吗
解决方案五:
哦 有个break
解决方案六:
基本思路是:任务执行类携带一个控制信息(标识是否有任务完成目标搜索),每次匹配规则之前,先检查该标识,如果非真,则进行规则匹配,若果该任务找到了目标,则修正该标识为真,通知其他任务结束。
示例代码如下,ControlInfo是控制信息,Task是任务类,Test是测试函数(定义控制信息和匹配规则,使用线程池提交任务)。
/**
- 全局控制控制信息
- 每个任务都关联一个该属性,任务之前之前先检查该标识,完成之后修正该标识
- @author bh
*/
public class ControlInfo {
private boolean isShouldFinished;
public boolean isShouldFinished() {
return isShouldFinished;
}
public void setShouldFinished(boolean isShouldFinished) {
this.isShouldFinished = isShouldFinished;
}
}
import java.util.List;/**
- 任务类处理规则:每次规则校验时先判断是否有其他线程找到
- 如果有其他线程已经完成,则结束;否则自己查找,找到通知其他线程
- @author bh
*/
public class Task implements Runnable{
private ControlInfo controlInfo;
private List rules;
public Task(ControlInfo controlInfo,List rules){
this.controlInfo = controlInfo;
this.rules = rules;
}@Override
public void run() {
//遍历规则,进行校验
for(String rule:rules){
//操作之前先判断是否有其他线程找到了,如果找到了就结束
synchronized(controlInfo){
if(!controlInfo.isShouldFinished()){
//TODO 判断规则处理:校验规则
if(rule.equals("")){
//找到了,通知其他任务,结束
controlInfo.setShouldFinished(true);
}
}else{
//有任务已经完成,则结束规则查找
return;
}
}
}
}
}
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
//开启一个线程池
ExecutorService exec = Executors.newFixedThreadPool(5);
//定义需校验的规则
List r1 = null;
List r2 = null;
List r3 = null;
List r4 = null;
List r5 = null;
//创建一个控制对象
ControlInfo controlInfo = new ControlInfo();
//创建N个任务,第二个参数是规则
Task t1 = new Task(controlInfo,r1);
Task t2 = new Task(controlInfo,r2);
Task t3 = new Task(controlInfo,r3);
Task t4 = new Task(controlInfo,r4);
Task t5 = new Task(controlInfo,r5);
//线程池执行任务
exec.execute(t1);
exec.execute(t2);
exec.execute(t3);
exec.execute(t4);
exec.execute(t5);
}
}