public class TheadMain {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Task());
thread.start();
}
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
static class Task implements Runnable{
@Override
public void run() {
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
}
}
Thread Name: Thread-7
Thread Name: main
Thread Name: Thread-4
Thread Name: Thread-2
Thread Name: Thread-9
Thread Name: Thread-5
Thread Name: Thread-0
Thread Name: Thread-6
Thread Name: Thread-8
Thread Name: Thread-1
Thread Name: Thread-3
ThreadPool
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TheadMain {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
service.execute(new Task());
}
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
static class Task implements Runnable{
@Override
public void run() {
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
}
}
Thread Name: pool-1-thread-9
Thread Name: pool-1-thread-3
Thread Name: pool-1-thread-5
Thread Name: pool-1-thread-4
Thread Name: pool-1-thread-8
Thread Name: pool-1-thread-10
Thread Name: pool-1-thread-2
Thread Name: pool-1-thread-7
Thread Name: main
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-6
ieal number of tp is the same as the number of cpu core
int coreCount = Runtime.getRuntime().availableProcessors()
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TheadMain {
public static void main(String[] args) {
// get count of available cores
int coreCount = Runtime.getRuntime().availableProcessors();
System.out.println(coreCount);
ExecutorService service = Executors.newFixedThreadPool(coreCount);
for (int i = 0; i < 10; i++) {
service.execute(new Task());
}
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
static class Task implements Runnable{
@Override
public void run() {
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
}
}
4
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-1
Thread Name: pool-1-thread-2
Thread Name: pool-1-thread-3
Thread Name: main
Thread Name: pool-1-thread-4
| Task Type | Ideal pool size | Considerations |
|---|---|---|
| CPU Intensive | Cpu core count | How many other applications(or other executors/threads) are running on the same CPU |
| IO intensive | High | Exact number will depend on rate of task submissions and average task wait time. Too many thread will increase memory consumption too |
Type of Pools
FixedThreadPool = newFixedThreadPool
CachedThreadPool
Synchronous queue(can hold only 1 task)
If all threads are busy, then create a new thread for the task and place it in the pool
Life cycle: If thread is idle for 60 seconds (no task to execute) then kill the thread
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TheadMain {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
service.execute(new Task());
}
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
static class Task implements Runnable{
@Override
public void run() {
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
}
}
ScheduledThreadPool
Service.schedule
Service.scheduleAtFixedRate
Service.scheduleAtFixedDelay
Schedule the tasks to run based on time delay (and retrigger for fixedRate / fixedDelay)
Life Cycle: More threads are created if required
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TheadMain {
public static void main(String[] args) {
// for scheduling of tasks
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
// task to run after 10 seconds delay
service.schedule(new Task(),10,TimeUnit.SECONDS);
// taks to run repeatedly every 10 seconds
service.scheduleAtFixedRate(new Task(), 15,10, TimeUnit.SECONDS);
// task to run repeatedely 10 seconds after previous task completes
service.scheduleWithFixedDelay(new Task(), 15,10,TimeUnit.SECONDS);
}
static class Task implements Runnable{
@Override
public void run() {
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
}
}
SingleThreadedExecutor
Life Cycle : Recreates thread if killed because of the task.
ExecutorService service = Executors.newFixedThreadPool(10);
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
생성자 파라미터
corePoolSize
Type: int
Minumum/Base size of the pool
maxPoolSize
Type: int
Maximum size of the pool
KeepAliveTime + unit
Type: long
Time to keep an idle thread alive(after which it is killed)
workQueue
Type: BlockingQueue
Queue to store the tasks from which threads fetch from
threadFactory
Type: ThreadFactory
The factory to use to create new threads
handler
Type: RejectedExecutionHandler
Callback to use when tasks submitted are rejected
Pool size changes
| Parameter | FixedThreadPool | CachedThreadPool | ScheduledThreadPool | SingleThreaded |
|---|---|---|---|---|
| corePoolsize | constructor-arg | 0 | constructor-arg | 1 |
| maxPoolSize | same as corePoolSize | Integer.MAX_VALUE | Integer.MAX_VALUE | 1 |
| keepAliveTime | 0 seconds | 60 seconds | 60 seconds | 0 seconds |
Queue types
Task rejections
Life cycle methods
Runnable interface
Thread Task return
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class TheadMain {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
List<Future> allFuture = new ArrayList<>();
for(int i=0; i<100;i++) {
Future<Integer> future = service.submit(new Task());
allFuture.add(future);
}
// 100 futures, with 100 placeholders;
// perform some unrelated operations
// 100 sec
for(int i=0; i<100; i++) {
Future<Integer> future = allFuture.get(i);
try {
Integer result = future.get(); // blocking
System.out.println("Result of future #" + i + "=" + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("Thread Name: " + Thread.currentThread().getName());
}
static class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Thread.sleep(3000);
return new Random().nextInt();
}
}
}