Skip to content

Instantly share code, notes, and snippets.

@georgemayko
Forked from rponte/HowToUseIt.java
Created September 22, 2020 12:43
Show Gist options
  • Save georgemayko/434da1c7cabcc29bf51d0d6612e66ef9 to your computer and use it in GitHub Desktop.
Save georgemayko/434da1c7cabcc29bf51d0d6612e66ef9 to your computer and use it in GitHub Desktop.
THEORY: Example of a simple Single Thread Pool implementation in Java
public class HowToUseIt {
/**
* Usually we'll have a single instance per client
*/
private static final SingleThreadPool THREAD_POOL = new SingleThreadPool();
public void executeAsync() {
try {
THREAD_POOL
.runInBackground(new PrintWorker());
} catch (RejectedExecutionException e) {
throw new RuntimeException("There's a thread running already!");
}
}
static class PrintWorker implements Runnable {
@Override
public void run() {
System.out.println("executing in background...");
}
}
}
package br.com.rponte.util.threads;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* ThreadFactory que permite definir o nome das threads criadas,
* facilitando assim tracing e logging das threads.
*
* <p>
* A factory cria threads com nomes na forma de <i>pool-{poolName}-thread-{N}</i>,
* onde <i>{poolName}</i> é a string fornecida no construtor, e <i>{N}</i> é
* o número sequencial da thread criada por essa factory.
*
* Inspirada na classe <code>Executors.DefaultThreadFactory</code> do JDK6.
*
* <p>
* http://dubravsky.com/b/seven-rules-of-executorservice-usage-in-java-rule-3-name-the-threads-of-a-thread-pool
* https://stackoverflow.com/questions/6113746/naming-threads-and-thread-pools-of-executorservice
*/
public class NamedThreadFactory implements ThreadFactory {
private final String poolName;
private final AtomicInteger threadNumber = new AtomicInteger(1);
public NamedThreadFactory(String poolName) {
this.poolName = poolName;
}
@Override
public Thread newThread(Runnable r) {
String threadName = "pool-{poolName}-thread-{N}"
.replace("{poolName}", poolName)
.replace("{N}", String.valueOf(threadNumber.getAndIncrement()))
;
Thread t = new Thread(r, threadName);
t.setDaemon(false);
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
package br.com.rponte.util.threads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Pool de thread de tamanho máximo 1. Rejeita execução caso já
* exista uma thread em andamento.
*/
public class SingleThreadPool {
/**
* Pool de thread de tamanho 1.<br/>
* A idéia é não permitir mais do que uma execução simultanea de uma thread
*/
private final ExecutorService THREAD_POOL = new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(), // rejeita tarefas excendentes
new NamedThreadFactory("my_pool")); // define nome para as threads
/**
* Executa worker em background porém não permite mais do que
* um worker por vez.
*
* Caso exista um processo em execução uma exceção <code>RejectedExecutionException</code>
* será lançada.
*/
public void runInBackground(Runnable worker) throws RejectedExecutionException {
THREAD_POOL.submit(worker);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment