How to manage M flows (1 per task), providing only N threads at a time. With N <M. In java
I have a task queue in java. This queue is in the table in the database.
I need:
- 1 thread for each task only
- No more than N threads running simultaneously. This is due to the fact that the threads interact with the database, and I do not want the connection database to be opened.
I think I could do something like:
final Semaphore semaphore = new Semaphore(N);
while (isOnJob) {
List<JobTask> tasks = getJobTasks();
if (!tasks.isEmpty()) {
final CountDownLatch cdl = new CountDownLatch(tasks.size());
for (final JobTask task : tasks) {
Thread tr = new Thread(new Runnable() {
@Override
public void run() {
semaphore.acquire();
task.doWork();
semaphore.release();
cdl.countDown();
}
});
}
cdl.await();
}
}
I know that there is an ExecutorService class, but I'm not sure if I can use it for this.
So you think this is the best way to do this? Or could you explain to me how the ExecutorService works to solve this problem?
final decision:
I think the best solution is something like:
while (isOnJob) {
ExecutorService executor = Executors.newFixedThreadPool(N);
List<JobTask> tasks = getJobTasks();
if (!tasks.isEmpty()) {
for (final JobTask task : tasks) {
executor.submit(new Runnable() {
@Override
public void run() {
task.doWork();
}
});
}
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
}
. BTW , , .
ExecutorService. , , newFixedThreadPool. , , , n .
- :
private static final ExecutorService executor = Executors.newFixedThreadPool(N);
// ...
while (isOnJob) {
List<JobTask> tasks = getJobTasks();
if (!tasks.isEmpty()) {
List<Future<?>> futures = new ArrayList<Future<?>>();
for (final JobTask task : tasks) {
Future<?> future = executor.submit(new Runnable() {
@Override
public void run() {
task.doWork();
}
});
futures.add(future);
}
// you no longer need to use await
for (Future<?> fut : futures) {
fut.get();
}
}
}
, , get , .
Achieving good performance also depends on the type of work that needs to be done in threads. If your database is a processing bottleneck, I will begin to pay attention to how your threads access the database. Using the connection pool is possible in order. This can help you achieve greater throughput, as worker threads can reuse database connections from the pool.