ืืืื
ืื, ืื ืื ื ืืืืขืื ืฉืื'ืืืื ืืฉ ืืืืื. ืืชื ืืืื ืืงืจืื ืขื ืื ืืกืงืืจื ืฉืืืชืจืชื Better together: Java and the Thread class. ืืืง ื' - ืืืื ืืืฆืื ืืืืจื .![ืขืืืฃ ืืืื: Java ืืืืชื Thread. ืืืง V - ืืืฆืข, ThreadPool, Fork/Join - 1](https://cdn.codegym.cc/images/article/71380a8a-a138-4ec7-92fc-de0340122567/800.jpeg)
public static void main(String[] args) throws Exception {
Runnable task = () -> {
System.out.println("Task executed");
};
Thread thread = new Thread(task);
thread.start();
}
ืืคื ืฉืืชื ืืืื ืืจืืืช, ืืงืื ืืื ืืืชืืื ืืฉืืื ืืื ืื ืืืคืืื ื, ืืื ืื ืื ื ืฆืจืืืื ืืืืืจ ืขืืื ืขืืืจ ืืฉืืื ืืืฉื. ืคืชืจืื ืืื ืืื ืืฉืื ืืืชื ืืฉืืื ื ืคืจืืช, ืืืฉื execute(Runnable runnable)
. ืืื ืืืืฆืจืื ืฉื ื'ืืืื ืฉืงืื ืืช ืืฆืืงืชื ื ืืืืืขื ืืืืฉืง Executor
:
public static void main(String[] args) throws Exception {
Runnable task = () -> System.out.println("Task executed");
Executor executor = (runnable) -> {
new Thread(runnable).start();
};
executor.execute(task);
}
ืืจืืจ ืฉืืงืื ืืื ืืื ืชืืฆืืชื ืืืชืจ: ืขืืฉืื ืื ืื ื ืคืฉืื ืืืชืืื ืงืื ืืื ืืืชืืื ืืช Runnable
ืืฉืจืฉืืจ. ืื ื ืืืจ, ืื? ืืื ืื ืจืง ืืืชืืื: ![ืขืืืฃ ืืืื: Java ืืืืชื Thread. ืืืง V - ืืืฆืข, ThreadPool, Fork/Join - 2](https://cdn.codegym.cc/images/article/3892b6af-f882-4093-8ce8-6368dbb020af/512.jpeg)
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html
Executor
ืืืืฉืง ืืฉ ืืืฉืง ExecutorService
ืืฉื ื. ื-Javadoc ืขืืืจ ืืืฉืง ืื ืืืืจ ืฉืืชืืจ ExecutorService
ืคืจื Executor
ืืืกืคืง ืฉืืืืช ืืืืืื ื- Executor
. ืื ืื ืืืคืฉืจ ืืงืื java.util.concurrent.Future
ืขื ืื ืช ืืขืงืื ืืืจ ืชืืืื ืืืืฆืืข. ืืขืืจ, ื- Better together: Java and the Thread class. ืืืง IV - ื ืืชื ืืืชืงืฉืจืืช, ืขืชืื ืืืืจืื
, ืกืงืจื ื ืืงืฆืจื ืืช ืืืืืืืช ืฉื Future
. ืื ืฉืืืช ืื ืืฃ ืคืขื ืื ืงืจืืช ืืืชื, ืื ื ืืฆืืข ืื ืืจืขื ื ืืช ืืืืืจืื ;) ืื ืขืื ืืืืจ ื-Javadoc? ืื ืืืืจ ืื ื ืฉืืฉ ืื ื java.util.concurrent.Executors
ืืคืขื ืืืืื ืฉืืืคืฉืจ ืื ื ืืืฆืืจ ืืืฉืืื ืืจืืจืช ืืืื ืฉื ExecutorService
.
ExecutorService
ืืืื ื ืกืงืืจ. ืขืืื ืExecutor
ืืืฆืข (ืืืืืจ ืืืชืงืฉืจ execute()
) ืืฉืืื ืืกืืืืช ืืฉืจืฉืืจ, ืืืงืื ืฉืืืฆืจ ืืช ืืฉืจืฉืืจ ืืืกืชืจ ืืืืชื ื. ืืฉ ืื ื ExecutorService
- ืกืคืฆืืคื Executor
ืฉืืฉ ืื ืืกืคืจ ืืคืฉืจืืืืช ืืฉืืืื ืืืชืงืืืืช. ืืืฉ ืื ื ืืช Executors
ืืืคืขื ืฉืืืคืฉืจ ืื ื ืืืฆืืจ ExecutorService
. ืขืืฉืื ืืืื ื ืขืฉื ืืืช ืืขืฆืื ื:
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> task = () -> Thread.currentThread().getName();
ExecutorService service = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
Future result = service.submit(task);
System.out.println(result.get());
}
service.shutdown();
}
ื ืืชื ืืจืืืช ืฉืฆืืื ื ืืืืจ ืืืืื ืงืืืข ืฉืืืืื ืืื 2. ืืืืจ ืืื ืื ื ืืืืฉืื ืืฉืืืืช ืืืืืจ ืืื ืืื. ืื ืืฉืืื ืืืืืจื a String
ืืืืื ืืช ืฉื ืืฉืจืฉืืจ ( currentThread().GetName()
). ืืฉืื ืืกืืืจ ืืช ืืชืืื ืืช ExecutorService
ืืืฉ ืืกืืฃ, ืื ืืืจืช ืืชืืื ืืช ืฉืื ื ืื ืชืกืชืืื. ืืืคืขื Executors
ืฉืืืืช ืืคืขื ื ืืกืคืืช. ืืืืืื, ื ืืื ืืืฆืืจ ืืจืืื ืืืืจืืืช ืืฉืจืฉืืจ ืืื ืืืื ( newSingleThreadExecutor
) ืื ืืืืจ ืืืืื ืืืืื ( newCachedThreadPool
) ืฉืืื ื ืืืกืจืื ืฉืจืฉืืจืื ืืืืจ ืฉืื ืื ืคืขืืืื ืืืฉื ืืงื. ืืืฆืืืืช, ืืื ExecutorService
ืืืืืื ืืชืืจ ืืกืืื , ืฉืืชืืื ืืืืงืืืช ืืฉืืืืช ืืืื ื ืืืืฆืขืืช ืืฉืืืืช. ืืืืข ื ืืกืฃ ืขื ืืกืืืช ืชืืจืื ื ืืชื ืืืฆืื ืืกืจืืื ืื
. ืืชื ืืืื ืื ืืงืจืื ืกืงืืจื ืื ืขื BlockingQueue
. ืืืืืง ืืช ืืชืฉืืื ืืฉืืื "ืืชื ืืืขืืืฃ LinkedBlockingQueue ืขื ืคื ื ArrayBlockingQueue?"
ืืืื ืืื ืืคืฉืืืื ืืืืชืจ, a BlockingQueue
ืืืกื ืืื ืืฉื ื ืืงืจืื:
- ืืฉืจืฉืืจ ืื ืกื ืืืฉืื ืคืจืืืื ืืชืืจ ืจืืง
- ืืฉืจืฉืืจ ืื ืกื ืืืื ืืก ืคืจืืืื ืืชืืจ ืืื
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
ืืึน
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ืืคื ืฉืื ื ืืืืืื ืืจืืืช, ืืืฉืืืื ืฉื ExecutorService
ื ืืฆืจืื ืืชืื ืฉืืืืช ืืืคืขื. ืืืจืื, ืื ืื ื ืืืืจืื ืขื ThreadPoolExecutor
. ืจืง ืืคืจืืืจืื ืืืฉืคืืขืื ืขื ืืขืืืื ืืฉืชื ืื. ![ืขืืืฃ ืืืื: Java ืืืืชื Thread. ืืืง V - ืืืฆืข, ThreadPool, Fork/Join - 3](https://cdn.codegym.cc/images/article/82252302-c8a0-4f20-b0e5-7ec8ea9a3b9e/800.jpeg)
https://en.wikipedia.org/wiki/Thread_pool#/media/File:Thread_pool.svg
ThreadPoolExecutor
ืืคื ืฉืจืืื ื ืงืืื,ThreadPoolExecutor
ืื ืื ืฉืืืจื ืืื ื ืืฆืจ ืืชืื ืฉืืืืช ืืืคืขื. ืืคืื ืงืฆืืื ืืืืช ืืืฉืคืขืช ืืืืจืืืื ืืื ืฉืื ื ืืขืืืจืื ืืืกืคืจ ืืืจืื ืืืืื ืืืื ืฉื ืฉืจืฉืืจืื, ืืื ืื ืืืืื ืกืื ืชืืจ ื ืขืฉื ืฉืืืืฉ. ืืื java.util.concurrent.BlockingQueue
ื ืืชื ืืืฉืชืืฉ ืืื ืืืฉืื ืฉื ืืืืฉืง. ืื ืืืจ ืืืืจืื ืขื ThreadPoolExecutor
, ืขืืื ื ืืืืืืจ ืืื ืชืืื ืืช ืืขื ืืื ืืช. ืืืืืื, ืื ื ืืชื ืืฉืืื ืืฉืืืืช ื- ThreadPoolExecutor
ืื ืืื ืืงืื ืคื ืื:
public static void main(String[] args) throws ExecutionException, InterruptedException {
int threadBound = 2;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, threadBound,
0L, TimeUnit.SECONDS, new SynchronousQueue<>());
Callable<String> task = () -> {
Thread.sleep(1000);
return Thread.currentThread().getName();
};
for (int i = 0; i < threadBound + 1; i++) {
threadPoolExecutor.submit(task);
}
threadPoolExecutor.shutdown();
}
ืืงืื ืืื ืืงืจืืก ืขื ืฉืืืื ืืื:
Task java.util.concurrent.FutureTask@7cca494b rejected from java.util.concurrent.ThreadPoolExecutor@7ba4f24f[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]
ืืืืืื ืืืจืืช, task
ืื ื ืืชื ืืืืืฉ, ืื SynchronousQueue
ืืื ืืชืืื ื ืื ืฉืืื ืืืขืฉื ืืืจืื ืืืืื ื ืืืื ืืื ืืืคืฉืจ ืื ื ืืืื ืืก ืื ืฉืื ืืืจ ื ืืกืฃ. ืื ืื ื ืืืืืื ืืจืืืช ืฉืืฉ ืื ื ืืคืก queued tasks
("ืืฉืืืืช ืืชืืจ = 0") ืืื. ืืื ืืื ืืื ืฉืื ืืืจ ืืืืจ, ืื ืื ืชืืื ื ืืืืืืช ืฉื SynchronousQueue
, ืฉืืืขืฉื ืืื ืชืืจ ืฉื ืืืื ื ืืื ืฉืชืืื ืจืืง! ืืืฉืจ ืฉืจืฉืืจ ืืื ืืื ืืก ืืืื ื ืืชืืจ, ืืื ืืืชืื ืขื ืฉืจืฉืืจ ืืืจ ืืืงื ืืช ืืืืื ื ืืืชืืจ. ืืืชืื ืืื, ื ืืื ืืืืืืฃ ืืืชื ื- new LinkedBlockingQueue<>(1)
ืืืฉืืืื ืชืฉืชื ื ืืืฆืืช ืืขืช queued tasks = 1
. ืืืืืื ืฉืืชืืจ ืืื ืจืง ืืืื ื ืืื, ืื ืื ื ืื ืืืืืื ืืืืกืืฃ ืืืื ื ืฉื ื. ืืื ืื ืฉืืืจื ืืชืืื ืืช ืืืืืฉื. ืืืืฉื ืืืืื ืฉืื ื ืขื ืชืืจ, ืจืืื ืืฆืืื ืฉืืืืชื ThreadPoolExecutor
ืืฉ ืฉืืืืช ื ืืกืคืืช ืืฉืืจืืช ืืชืืจ. ืืืืืื, threadPoolExecutor.purge()
ืืฉืืื ืชืกืืจ ืืช ืื ืืืฉืืืืช ืฉืืืืื ืืืชืืจ ืขื ืื ืช ืืคื ืืช ืืงืื ืืชืืจ. ืคืื ืงืฆืื ืืขื ืืื ืช ื ืืกืคืช ืืงืฉืืจื ืืชืืจ ืืื ืืืืคื ืืืฉืืืืช ืฉื ืืื:
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1,
0L, TimeUnit.SECONDS, new SynchronousQueue());
Callable<String> task = () -> Thread.currentThread().getName();
threadPoolExecutor.setRejectedExecutionHandler((runnable, executor) -> System.out.println("Rejected"));
for (int i = 0; i < 5; i++) {
threadPoolExecutor.submit(task);
}
threadPoolExecutor.shutdown();
}
ืืืืืื ืื, ืืืืคื ืฉืื ื ืคืฉืื ืืฆืื Rejected
ืืื ืคืขื ืฉืืฉืืื ืืชืืจ ื ืืืืช. ื ืื, ืื? ืื ืืกืฃ, ThreadPoolExecutor
ืืฉ ืชืช-ืืืืงื ืืขื ืืื ืช: ScheduledThreadPoolExecutor
, ืฉืืื ScheduledExecutorService
. ืืื ืืกืคืง ืืช ืืืืืืช ืืืฆืข ืืฉืืื ืขื ืืกืืก ืืืืืจ.
ScheduledExecutorService
ScheduledExecutorService
(ืฉืื ืกืื ืฉื ExecutorService
) ืืืคืฉืจ ืื ื ืืืจืืฅ ืืฉืืืืช ืืคื ืืื ืืื ืื. ืืืื ื ืกืชืื ืขื ืืืืื:
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
Callable<String> task = () -> {
System.out.println(Thread.currentThread().getName());
return Thread.currentThread().getName();
};
scheduledExecutorService.schedule(task, 1, TimeUnit.MINUTES);
scheduledExecutorService.shutdown();
}
ืืื ืคืฉืื ืืื. ืืืฉืืืืช ืืืืฉืืช ืืื ืื ืื ื ืืงืืืื java.util.concurrent.ScheduledFuture
. ืืื ืืื ืื ืขืฉืื ืืืืืช ืืืขืื ืื ืืืฆื ืืื:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
Runnable task = () -> {
System.out.println(Thread.currentThread().getName());
};
scheduledExecutorService.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS);
ืืื ืื ื ืืืืฉืื Runnable
ืืฉืืื ืืืืฆืืข ืืชืืืจืืช ืงืืืขื ("FixedRate") ืขื ืขืืืื ืจืืฉืื ื ืืกืืื. ืืืงืจื ืื, ืืืืจ ืฉื ืืื ืืืช, ืืืฉืืื ืชืชืืื ืืืชืืฆืข ืื 2 ืฉื ืืืช. ืืฉ ืืคืฉืจืืช ืืืื:
scheduledExecutorService.scheduleWithFixedDelay(task, 1, 2, TimeUnit.SECONDS);
ืืื ืืืงืจื ืื, ืืืฉืืืืช ืืืืฆืขืืช ืขื ืืจืืื ืืกืืื ืืื ืื ืืืฆืืข. ืืืืืจ, ืืฆืืืื task
ืชืชืืฆืข ืืืืจ ืฉื ืืื ืืืช. ืืืืจ ืืื, ืืจืืข ืฉืืื ืชืืฉืื, ืืขืืจื 2 ืฉื ืืืช, ืืื ืชืชืืื ืืฉืืื ืืืฉื. ืืืื ืืกืคืจ ืืฉืืืื ื ืืกืคืื ืื ืืฉื ืื:
- ืืืื ืืืจืืืืช ืืืืื ืื'ืืืื
- ืืืื ื-Thread Pools ื-Java
- ื'ืืืื Multithreading Steplechase: ืืืืื ืืฉืืืืช ื-Executors
- ืฉืืืืฉ ื-Java Executors ืขืืืจ ืืฉืืืืช ืจืงืข
![ืขืืืฃ ืืืื: Java ืืืืชื Thread. ืืืง V - ืืืฆืข, ThreadPool, Fork/Join - 4](https://cdn.codegym.cc/images/article/75c9ba8e-5102-494c-9d5f-ab9887ec8f20/800.jpeg)
https://dzone.com/articles/diving-into-java-8s-newworkstealingpools
WorkStealingPool
ืื ืืกืฃ ืืืจืืืืช ืืืืืื ืื "ื, ืืฉ ืขืื ืืืช. ืื ืื ื ืืืืืื ืืืืจ ืืื ืืช ืฉืื ืงืฆืช ืืืืื. ืื ื ืงืจื ืืจืืืช ืื ืืืช ืขืืืื. ืืงืืฆืืจ, ืื ืืืช ืขืืืื ืืื ืืืืืจืืชื ืฉืื ืฉืจืฉืืจืื ืกืจืง ืืชืืืืื ืืงืืช ืืฉืืืืช ืืฉืจืฉืืจืื ืืืจืื ืื ืืฉืืืืช ืืชืืจ ืืฉืืชืฃ. ืืืื ื ืกืชืื ืขื ืืืืื:public static void main(String[] args) {
Object lock = new Object();
ExecutorService executorService = Executors.newCachedThreadPool();
Callable<String> task = () -> {
System.out.println(Thread.currentThread().getName());
lock.wait(2000);
System.out.println("Finished");
return "result";
};
for (int i = 0; i < 5; i++) {
executorService.submit(task);
}
executorService.shutdown();
}
ืื ื ืจืืฅ ืืช ืืงืื ืืื, ืื ืื ExecutorService
ืืืฆืืจ ืขืืืจื ื 5 ืฉืจืฉืืจืื, ืืืืืื ืฉืื ืฉืจืฉืืจ ืืืื ืก ืืชืืจ ืืืืชื ื ืืืืืืืงื ืื ืขืืื. ืืืจ ืืืืื ื ืฆืืื ืืื ืขืืืื ื- Better ืืืื: Java ืืืืืงืช Thread. ืืืง ื' - ืกื ืืจืื
. ืขืืฉืื ืืืื ื ืืืืฃ Executors.newCachedThreadPool()
ื Executors.newWorkStealingPool()
. ืื ืืฉืชื ื? ื ืจืื ืฉืืืฉืืืืช ืฉืื ื ืืืืฆืขืืช ืืคืืืช ื-5 ืฉืจืฉืืจืื. ืืืืจืื ืฉืื CachedThreadPool
ืืืฆืจ ืฉืจืฉืืจ ืืื ืืฉืืื? ืืกืืื ืืื ืืื wait()
ืฉืืกืื ืืช ืืฉืจืฉืืจ, ืืฉืืืืช ืขืืงืืืช ืจืืฆืืช ืืืกืชืืื, ืื ืืฆืจื ืขืืืจื ืฉืจืฉืืจืื ืืืฉืื ืืืืืจ. ืขื ืืจืืื ืื ืืื, ืืืืื ืื ืขืืืืื ืืืืื ืื ืฆื. ืื ืืชืืืืื ืืืฆืข ืืช ืืืฉืืืืช ืฉื ืฉืื ืืื. ืื ืขืืฉื WorkStealingPool
ืื ืื ืฉืื ื ืืืจืืืืช ืืืืื ืืืจืืช? ืืขืืืื ืฉืืงืกืื ForkJoinPool
ืื ืืชืืื:
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
ืืืขืฉื, ืืฉ ืขืื ืืืื ืืื. ืืืจืืจืช ืืืื, ืืฉืจืฉืืจืื ืฉื ืืฆืจื ืขืืืจ a ForkJoinPool
ืื ืฉืจืฉืืจื ืืืื, ืืฉืื ื ืืืฉืจืฉืืจืื ืฉื ืืฆืจื ืืืืฆืขืืช ืฉืจืฉืืจ ืจืืื ThreadPool
. ืืืืคื ืืืื, ืืชื ืฆืจืื ืืืืืจ ืฉืจืฉืืจื ืืืื, ืืืืืื, ืืืฉื, CompletableFuture
ืืฉืชืืฉ ืื ืืฉืจืฉืืจื ืืืื ืืื ืื ืื ืืชื ืืฆืืื ืืฉืื ThreadFactory
ืฉืืืฆืจ ืฉืจืฉืืจืื ืฉืืื ื ืืืื ืื. ืืื ืืืคืชืขืืช ืฉืขืืืืืช ืืืืืช ืืืจืืืช ืืืงืืืืช ืื ืฆืคืืืื! :)
ForkJoinPool
ืืืืง ืื, ื ืืืจ ืฉืื ืขืForkJoinPool
(ืื ืงืจืืช ืื ืืกืืจืช ืืืืื/ืืืืจ), ืฉืื "ืืชืืช ืืืืกื ืืื ืืข" ืฉื WorkStealingPool
. ืืืืคื ืืืื, ืืืกืืจืช fork/join ืืืคืืขื ืืืืจื ื-Java 1.7. ืืืืจืืช ืฉ-Java 11 ืงืจืืื, ืขืืืื ืืืื ืืืืืจ ืืืชื. ืื ืื ืืืืฉืื ืื ืคืืฅ ืืืืชืจ, ืืื ืืื ืื ืืขื ืืื. ืืฉ ืกืงืืจื ืืืื ืขื ืื ืืืื ืืจื ื: ืืื ืช Java Fork-Join Framework ืขื ืืืืืืืช
. ืืืกืชืืืช ForkJoinPool
ืขื java.util.concurrent.RecursiveTask
. ืืฉ ืื java.util.concurrent.RecursiveAction
. RecursiveAction
ืื ืืืืืจ ืชืืฆืื. ืืคืืื, RecursiveTask
ืืืื ื Callable
, ืืืืื RecursiveAction
ื unnable
. ืื ื ืืืืืื ืืจืืืช ืฉืืฉื ืืืื ืฉืืืช ืฉื ืฉืชื ืฉืืืืช ืืฉืืืืช: fork
ื join
. ืืฉืืื fork
ืืชืืืื ืืฉืืื ืืืฉืื ืืืืคื ืืกืื ืืจืื ื ืืฉืจืฉืืจ ื ืคืจื. ืืืฉืืื join
ืืืคืฉืจืช ืื ืืืืืช ืืขืืืื ืฉืชืชืืฆืข. ืืื ืืงืื ืืช ืืืื ื ืืืืื ืืืืชืจ, ืืืื ืืงืจืื ืืชืื ืืช ืฆืืืื ื-Fork/Join ืืืจืืื ืืงืืืืื ื-Java 8
.
ืกืืืื
ืืืื, ืื ืืกืื ืืช ืืืืง ืืื ืฉื ืืกืงืืจื. ืืืื ื ืฉืืExecutor
ืืืืฆื ืืืงืืจ ืืื ืืืฆืข ืฉืจืฉืืจืื. ืืื ืืืืฆืจืื ืฉื ื'ืืืื ืืืืืื ืืืืฉืื ืืจืขืืื ืืืขืื ExecutorService
. ExecutorService
ืืืคืฉืจ ืื ื ืืฉืืื ืืฉืืืืช ืืืืฆืืข ืืืืฆืขืืช submit()
ื invoke()
, ืืื ืืืืืช ืืช ืืฉืืจืืช. ืืืืืื ExecutorService
ืฉืฆืจืื ืืืฉืืืื, ืื ืืชืื ืืืืงื ืขื ืฉืืืืช ืืคืขื ืืงืจืื ืืื Executors
. ืื ืืืคืฉืจ ืื ืืืฆืืจ ืืจืืืืช ืืืืื ( ThreadPoolExecutor
). ืื ืืกืฃ, ืืฉื ื ืืจืืืืช ืฉืจืฉืืจืื ืืืืคืฉืจืืช ืื ื ืื ืืฆืืื ืืื ืืื ืื ืืืืฆืืข. ืืืกืชืชืจ ForkJoinPool
ืืืืืจื ื WorkStealingPool
. ืื ื ืืงืืื ืฉืืฆืืช ืืช ืื ืฉืืชืืชื ืืืขืื ืื ืจืง ืืขื ืืื, ืืื ืื ืืืื :) ืื ื ืชืืื ืฉืื ืืฉืืืข ืืช ืืืฆืขืืช ืืืืขืจืืช ืฉืื. ืขืืืฃ ืืืื: Java ืืืืชื Thread. ืืืง ื' - ืืืื ืืืฆืืข
ืืื ืืืชืจ ืืืื: ื'ืืืื ืืืืืงืช ื-Thread. ืืืง ื' - ืกื ืืจืื
ืืื ืืืชืจ ืืืื: Java ืืืืืงืช Thread. ืืืง ืฉืืืฉื - ืืื ืืจืืงืฆืื
ืืืื ืืืชืจ ืืืื: Java ืืืืืงืช Thread. ืืืง IV โ ื ืืชื ืืืชืงืฉืจืืช, ืขืชืื ืืืืจืื
ืืืืื ืืืชืจ ืืืื: Java ืืืืชื Thread. ืืืง ื' - ืืฉ!
GO TO FULL VERSION