具有单个工作进程和返回值的Java多线程异步调用

具有单个工作进程和返回值的Java多线程异步调用,java,multithreading,Java,Multithreading,我已经为以下棘手的问题奋斗了几天: 我有一个基于tomcat的web应用程序,可以在任意时间向查询服务器发出请求。可能会同时触发两个或多个请求 在接收端,我有一个处理这些请求的服务器,在仔细考虑这些请求之后,将结果列表返回到Tomcat,该列表显示在jsp页面上 服务器只有一个对象的静态实例,该实例实际上会在数据中翻腾(创建成本相当高) 现在我遇到了一个瓶颈:一方面,来自Tomcat的请求应该同步处理,以便Tomcat内部的管道能够工作并向用户显示合理的结果。 另一方面,如果它们是同步提供的,则

我已经为以下棘手的问题奋斗了几天:

我有一个基于tomcat的web应用程序,可以在任意时间向查询服务器发出请求。可能会同时触发两个或多个请求

在接收端,我有一个处理这些请求的服务器,在仔细考虑这些请求之后,将结果列表返回到Tomcat,该列表显示在jsp页面上

服务器只有一个对象的静态实例,该实例实际上会在数据中翻腾(创建成本相当高)

现在我遇到了一个瓶颈:一方面,来自Tomcat的请求应该同步处理,以便Tomcat内部的管道能够工作并向用户显示合理的结果。 另一方面,如果它们是同步提供的,则处理方法(askQuery())对于其他线程显示为锁定,并且辅助请求返回空

我已经尝试了(几乎)所有可能的事情:在单独的线程中运行处理,同步方法,等等——到目前为止都没有效果。如果处理在一个单独的线程中运行,我无法生成结果并将列表同步返回给Tomcat。如果我join()线程,该方法将显示为锁定

下面是我想做的事情的原始类:

    package...
    imports...

    public class DLQueryEngineBrain extends ADLQueryEngine{
        protected static Brain brain;
        protected static boolean isFree = true;
        protected AOwlResultParser orp;
        private QueryThread queryThread;


        public DLQueryEngineBrain(String ontologyURL, ThirdPartyBeanManager tpbm) {
            super(ontologyURL, tpbm);
            try {
                DLQueryEngineBrain.brain = new Brain("http://purl.obolibrary.org/obo/", "http://purl.obolibrary.org/obo/fbbt.owl", 32);
                LOG.debug("BRAIN': " + brain + " this " + this);
                brain.learn(ontologyURL);
            } 
            catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            this.orp = new OwlResultParserClass(this.ontology);
        }

    // This is the method I want to run asynchronously, but I want it to return results //in-line of the calling method, eg. 
    //results = queryEngineBrain.askQuery("sublcass of some X"), and use the results in the //subsequent code...

public synchronized Set<OntBean> askQuery(OntQueryQueue oqq) {
            LOG.debug("Input: " + oqq.toString());
            Set<OntBean> results = new TreeSet<OntBean>();
            QueryThread queryThread = new QueryThread(oqq, (OwlResultParserClass)this.orp);
            queryThread.start();
            while (!queryThread.isFinished){
                try {
                    Thread.sleep(10);
                    LOG.debug("Main Thread sleeps...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            LOG.debug("Output: " + queryThread.results.size());
            return queryThread.results;
        }

        class QueryThread extends Thread {
            int number;
            private Set<OntBean> results = new TreeSet<OntBean>();
            private OntQueryQueue oqq;
            private OwlResultParserClass orp;
            boolean isFinished = false;


            //Just save the number to display on the console
            public QueryThread(OntQueryQueue oqq, OwlResultParserClass orp) {
                this.number = DLQueryEngineBrain.numThreads++;
                this.oqq = oqq;
                this.orp = orp;
            }

            public void run () {
                while(!this.isFinished) {
                    LOG.debug("DLQueryEngineBrain.isFree: " + DLQueryEngineBrain.isFree);
                    if (DLQueryEngineBrain.isFree){
                        this.runQuery();
                        this.isFinished = true;
                    }
                    else {
                        LOG.debug("Query thread sleeps while brain is busy...");
                        try {
                            Thread.sleep(getRandInt());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            public void runQuery() {
                DLQueryEngineBrain.isFree = false;
                List<String> queries = this.oqq.getQueries();
                LOG.debug("BRAIN : " + DLQueryEngineBrain.brain + " this " + this);
                for (String currExpr: queries){
                    LOG.debug("currExpr: " + currExpr);     
                    List<String> subClasses = null;
                    try {
                        subClasses = DLQueryEngineBrain.brain.getSubClasses(currExpr, true);
                    } catch (ClassExpressionException e) {
                        e.printStackTrace();
                    }
                    LOG.debug("Found: " + subClasses.size());
                    //Iterates over the list and print the result.
                    for (String subClass : subClasses) {
                        this.results.add(orp.getOntBeanForId(subClass));
                    }
                }
                DLQueryEngineBrain.isFree = true;
            }

            private int getRandInt(){
                double d = Math.random();
                int i = Math.round((float)d*100); 
                return i;
            }
        }

    }
包。。。
进口。。。
公共类DLQueryEngineBrain扩展了ADLQueryEngine{
保护静态脑;
受保护的静态布尔值isFree=true;
受保护的AOWLResultPasser orp;
私有查询读取查询读取;
公共DLQueryEngineBrain(字符串本体URL,第三方BeanManager tpbm){
super(本体论,tpbm);
试一试{
DLQueryEngineBrain.brain=新大脑(“http://purl.obolibrary.org/obo/", "http://purl.obolibrary.org/obo/fbbt.owl", 32);
LOG.debug(“BRAIN':”+BRAIN+“this”+this);
大脑学习(本体论);
} 
捕获(例外e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
this.orp=新的OwlResultParserClass(this.ontology);
}
//这是我想要异步运行的方法,但我希望它在调用方法的行中//返回结果,例如。
//results=queryEngineBrain.askQuery(“某些X的子类”),并在//后续代码中使用结果。。。
公共同步设置askQuery(OntQueryQueue oqq){
LOG.debug(“输入:+oqq.toString());
设置结果=新树集();
QueryThread QueryThread=newquerythread(oqq,(OwlResultParserClass)this.orp);
queryThread.start();
而(!queryThread.isFinished){
试一试{
睡眠(10);
调试(“主线程休眠…”);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
LOG.debug(“输出:+queryThread.results.size());
返回queryThread.results;
}
类QueryThread扩展线程{
整数;
私有集结果=新树集();
专用OntQueryQueue oqq;
私人有限责任公司;
布尔值isFinished=false;
//只需保存要在控制台上显示的号码
公共查询读取(OntQueryQueue oqq、OwlResultParserClass orp){
this.number=DLQueryEngineBrain.numThreads++;
this.oqq=oqq;
this.orp=orp;
}
公开作废运行(){
而(!this.isFinished){
LOG.debug(“DLQueryEngineBrain.isFree:+DLQueryEngineBrain.isFree”);
如果(DLQueryEngineBrain.isFree){
this.runQuery();
this.isFinished=true;
}
否则{
调试(“查询线程在大脑忙碌时休眠…”);
试一试{
sleep(getRandInt());
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}
公共void runQuery(){
DLQueryEngineBrain.isFree=false;
List querys=this.oqq.getquerys();
LOG.debug(“BRAIN:+DLQueryEngineBrain.BRAIN+“this”+this”);
for(字符串currExpr:querys){
LOG.debug(“currExpr:+currExpr”);
列表子类=null;
试一试{
subclass=DLQueryEngineBrain.brain.getsubclass(currExpr,true);
}捕获(ClassExpressionException e){
e、 printStackTrace();
}
LOG.debug(“发现:+子类.size());
//迭代列表并打印结果。
for(字符串子类:子类){
add(orp.getOntBeanForId(子类));
}
}
DLQueryEngineBrain.isFree=true;
}
私有int getRandInt(){
double d=Math.random();
int i=数学四舍五入((浮点)d*100);
返回i;
}
}
}
问题是askQuery()仍然锁定,所有后续查询都返回空结果

从askQuery()中删除Thread.sleep()会导致它异步工作,但不会返回任何结果-askQuery()代码只执行到最后,而不等待线程完成

感谢您对我所做错事的任何帮助或建议。

一个可能的原因是
public synchronized ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res) throws Exception { .. }`
 public class GeneListController implements Controller{