Which ThreadPool in Java should I use?

前端 未结 5 1737
花落未央
花落未央 2021-02-06 06:00

There are a huge amount of tasks. Each task is belong to a single group. The requirement is each group of tasks should executed serially just like executed in a single thread an

5条回答
  •  一整个雨季
    2021-02-06 06:32

    I mostly agree on Dave's answer, but if you need to slice CPU time across all "groups", i.e. all task groups should progress in parallel, you might find this kind of construct useful (using removal as "lock". This worked fine in my case although I imagine it tends to use more memory):

    class TaskAllocator {
        private final ConcurrentLinkedQueue> entireWork
             = childQueuePerTaskGroup();
    
        public Queue lockTaskGroup(){
            return entireWork.poll();
        }
    
        public void release(Queue taskGroup){
            entireWork.offer(taskGroup);
        }
     }
    

    and

     class DoWork implmements Runnable {
         private final TaskAllocator allocator;
    
         public DoWork(TaskAllocator allocator){
             this.allocator = allocator;
         }
    
         pubic void run(){
            for(;;){
                Queue taskGroup = allocator.lockTaskGroup();
                if(task==null){
                    //No more work
                    return;
                }
                Runnable work = taskGroup.poll();
                if(work == null){
                    //This group is done
                    continue;
                }
    
                //Do work, but never forget to release the group to 
                // the allocator.
                try {
                    work.run();
                } finally {
                    allocator.release(taskGroup);
                }
            }//for
         }
     }
    

    You can then use optimum number of threads to run the DoWork task. It's kind of a round robin load balance..

    You can even do something more sophisticated, by using this instead of a simple queue in TaskAllocator (task groups with more task remaining tend to get executed)

    ConcurrentSkipListSet> sophisticatedQueue = 
        new ConcurrentSkipListSet(new SophisticatedComparator());
    

    where SophisticatedComparator is

    class SophisticatedComparator implements Comparator> {
        public int compare(MyQueue o1, MyQueue o2){
            int diff = o2.size() - o1.size();
            if(diff==0){
                 //This is crucial. You must assign unique ids to your 
                 //Subqueue and break the equality if they happen to have same size.
                 //Otherwise your queues will disappear...
                 return o1.id - o2.id;
            }
            return diff;
        }
     }
    

提交回复
热议问题