Java线程 - 等待返回数据,但不阻止其他线程

时间:2017-04-26 18:18:31

标签: java multithreading threadpoolexecutor

我在ExecutorPool中运行了7个线程来处理数据,偶尔也需要来自另一个线程上运行的侦听器实例的数据。侦听器通过套接字向服务器发送请求,稍后,当返回结果时,侦听器将数据返回给调用它的工作线程。我想阻止工作线程,直到返回请求的数据,但我不想阻止侦听器从其他工作线程发出其他请求。我该怎么做?

2 个答案:

答案 0 :(得分:2)

如果一个线程将工作移交给另一个线程,然后随后只是等待结果,那么您不需要另一个线程来完成工作。您可能需要一个完成工作的类,但在同一个线程上调用它。如果多个线程使用相同的实例,则可能需要一些同步。但最重要的是:

您不需要侦听线程。将其替换为处理请求的组件,并同步调用它。

<强> 修改

鉴于您自己的答案,您的问题会更清楚一些。正如@JimN建议您可能希望向工作线程分发Future,并使其成为CompletableFuture,监听器保留在Map中,并按请求ID键入,直到响应返回。 / p>

示例代码:

public class WorkUnitProcessor implements Runnable {

    // ...

    @Override
    public void run() {
        while(true) {
            WorkUnit work = master.getNextWorkUnit();
            if(work == null) return;
            doWork(work);
        }
    }

    public void doWork(WorkUnit work) {

        //Do some work...

        try {
            DataRequest dataRequest = createRequest(work);

            Future<Response> future = server.getData(dataRequest);
            Response response = future.get();                       // this call blocks until the Response is available.

            //finish doing work

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException e) {
            // handle e.getCause()
        }

    }

    // ...
}

public class Server implements DataSourceDrivenCallback {

    private final DataSource dataSource;

    private Map<Integer, CompletableFuture<Response>> openRequests = new ConcurrentHashMap<>();

    public Server(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void incomingDataCallback(int requestId, ChunkOfData requestedData) {
        CompletableFuture<Response> responseHolder = openRequests.remove(requestId);  // get the responseHolder
        if (responseHolder != null) {
            responseHolder.complete(toResponse(requestedData));                     // make the response available.
        }
    }

    public Future<Response> getData(DataRequest datarequest) {
        int requestId = dataSource.submitRequest(serializeAndTranslateRequest(datarequest));
        CompletableFuture<Response> future = new CompletableFuture<>();
        openRequests.put(requestId, future);
        return future;
    }

    // ...
}

答案 1 :(得分:0)

我认为这可能有效。我在寻找的是这里描述的:

https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

能够使线程休眠,直到线程通知它正在等待。似乎很容易使用。

"sqs://id:key@:80"