Thread pool that binds tasks for a given ID to the same thread

前端 未结 6 1895
别那么骄傲
别那么骄傲 2020-12-28 17:19

Are there any implementations of a thread pool (in Java) that ensures all tasks for the same logical ID are executed on the same thread?

The logic I\'m after is if t

6条回答
  •  遥遥无期
    2020-12-28 18:08

    The simplest idea could be this:

    Have a fixed map of BlockingQueues. Use hash mechanism to pick a queue based on task id. The hash algorithm should pick the same queue for the same ids. Start one single thread for every queue. every thread will pick one task from it's own dedicated queue and execute it.

    p.s. the appropriate solution is strongly depends on the type of work you assign to threads

    UPDATE

    Ok, how about this crazy idea, please bear with me :)

    Say, we have a ConcurrentHashMap which holds references id -> OrderQueue

    ID1->Q1, ID2->Q2, ID3->Q3, ...
    

    Meaning that now every id is associated with it's own queue. OrderQueue is a custom blocking-queue with an additional boolean flag - isAssociatedWithWorkingThread.

    There is also a regular BlockingQueue which we will call amortizationQueue for now, you'll see it's use later.

    Next, we have N working threads. Every working thread has it's own working queue which is a BlockingQueue containing ids associated with this thread.

    When a new id comes, we do the following:

    create a new OrderQueue(isAssociatedWithWorkingThread=false)
    put the task to the queue
    put id->OrderQueue to the map
    put this OrderQueue to amortizationQueue
    

    When an update for existing id comes we do the following:

    pick OrderQueue from the map
    put the task to the queue
    if isAssociatedWithWorkingThread == false
        put this OrderQueue to amortizationQueue
    

    Every working thread does the following:

    take next id from the working queue
    take the OrderQueue associated with this id from the map
    take all tasks from this queue
    execute them
    mark isAssociatedWithWorkingThread=false for this OrderQueue
    put this OrderQueue to amortizationQueue
    

    Pretty straightforward. Now to the fun part - work stealing :)

    If at some point of time some working thread finds itself with empty working queue, then it does the following:

    go to the pool of all working threads
    pick one (say, one with the longest working queue)
    steal id from *the tail* of that thread's working queue
    put this id to it's own working queue
    continue with regular execution
    

    And there also +1 additional thread which provides amortization work:

    while (true)
        take next OrderQueue from amortizationQueue
        if queue is not empty and isAssociatedWithWorkingThread == false
             set isAssociatedWithWorkingThread=true
             pick any working thread and add the id to it's working queue
    

    Will have to spend more time thinking if you can get away with AtomicBoolean for isAssociatedWithWorkingThread flag or there is a need to make it blocking operation to check/change this flag.

提交回复
热议问题