All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.facebook.presto.jdbc.internal.airlift.concurrent.BoundedExecutor Maven / Gradle / Ivy

There is a newer version: 0.289
Show newest version
package com.facebook.presto.jdbc.internal.airlift.concurrent;

import com.facebook.presto.jdbc.internal.guava.base.Preconditions;
import com.facebook.presto.jdbc.internal.airlift.log.Logger;

import javax.annotation.concurrent.ThreadSafe;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 

* Guarantees that no more than maxThreads will be used to execute tasks submitted * through execute(). *

* There are a few interesting properties: * - Multiple BoundedExecutors over a single coreExecutor will have fair sharing * of the coreExecutor threads proportional to their relative maxThread counts, but * can use less if not as active. * - Tasks submitted to a BoundedExecutor is guaranteed to have those tasks handed to * threads in that order. * - Will not encounter starvation */ @ThreadSafe public class BoundedExecutor implements Executor { private static final Logger log = Logger.get(BoundedExecutor.class); private final Queue queue = new ConcurrentLinkedQueue<>(); private final AtomicInteger queueSize = new AtomicInteger(0); private final Runnable triggerTask = new Runnable() { @Override public void run() { executeOrMerge(); } }; private final Executor coreExecutor; private final int maxThreads; public BoundedExecutor(Executor coreExecutor, int maxThreads) { Preconditions.checkNotNull(coreExecutor, "coreExecutor is null"); Preconditions.checkArgument(maxThreads > 0, "maxThreads must be greater than zero"); this.coreExecutor = coreExecutor; this.maxThreads = maxThreads; } @Override public void execute(Runnable task) { queue.add(task); coreExecutor.execute(triggerTask); // INVARIANT: every enqueued task is matched with an executeOrMerge() triggerTask } private void executeOrMerge() { int size = queueSize.incrementAndGet(); if (size <= maxThreads) { do { try { queue.poll().run(); } catch (Throwable e) { log.error(e, "Task failed"); } } while (queueSize.getAndDecrement() > maxThreads); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy