使用线程池的原因是为了降低系统资源消耗,提高应用程序的性能和效率,若不使用线程池而总是启动新线程来执行多任务,会降低
系统资源的利用率。开启一个线程的代价是比较大的,开启线程并非只是消耗JVM资源,而且会面向系统申请资源。thread类的start0()
方法是个native方法,必然会由系统分配相关线程资源。
系统资源的利用率。开启一个线程的代价是比较大的,开启线程并非只是消耗JVM资源,而且会面向系统申请资源。thread类的start0()
方法是个native方法,必然会由系统分配相关线程资源。
private native void start0();
因此引入线程池,提高系统资源利用率,java常用的四种线程池解释及使用如下:
1.CachedThreadPool
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/** 官方释义:
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to <tt>execute</tt> will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*
* 翻译(大致意思):创建一个应用程序需要多个线程的线程池,但是应用程序会重用之前构造的可用的
* 空闲线程,它会显著的提升应用程序执行短耗时异步类型的任务。如果线程池中没有可用的线程,那
* 么将会创建一个新线程并将其加入到线程池中。如果线程在60s内没有被使用,那么该线程将会被回收
* 并且从缓存中移出,因此,该类型线程池会留存足够长的时间且不会消耗任何资源。
*
*
*/
public class CachedThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
executor.execute(new Runnable() {
public void run() {
String name = Thread.currentThread().getName();
System.out.println("name" + name);
}
});
}
executor.shutdown();
}
}
执行程序结果如下:
1处是第一个线程执行时的线程名为namepool-1-thread-1,启东第二线程时,休眠了1秒,此时第一个线程早已执行完成,
线程已经空出,所以第二个线程执行的时候依然使用的是第一个,因此线程名是相同的。
线程已经空出,所以第二个线程执行的时候依然使用的是第一个,因此线程名是相同的。
2.FixedThreadPool
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 官方释义:
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* <tt>nThreads</tt> threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*
* 翻译(大致意思):创建一个固定数量的线程池,操作一个共享无边界的队列。任何时刻,最多只有
* 指定数量的线程处理任务,如果当有额外的任务被提交到线程池但没有空闲线程可供使用时,则该
* 任务会被放到队列中直到出现空闲线程,一旦有任一线程在执行完成前因失败而被终止,那么一个
* 新的任务将会取代它进而执行后续的任务。
*
*/
public class FixedThreadPoolTest {
private static int nThreads = 5;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
for(int i=1;i<=10;i++){
executor.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("当前线程:"+Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
executor.shutdown();
}
}
执行程序首先打印如下信息:
因为线程池的初始化大小为5,但是开启了10个线程,所以实际上只开启了5个。由于没有可用的线程,所以程序阻塞,
直到5个线程允许完毕后,另外5个线程开始执行。
直到5个线程允许完毕后,另外5个线程开始执行。
3.ScheduledThreadPool
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
*
* 周期性或定时执行任务
*
*/
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
//5表示线程池中保持5个线程,即使是空闲的。
ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
ses.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("hello world!!!");
}
}, 2, 3, TimeUnit.SECONDS);//2秒后执行,每隔3秒执行一次
// ses.scheduleAtFixedRate(command, initialDelay, period, unit)
// ses.schedule(callable, delay, unit)
// ses.shutdown();
}
}
如图:程序运行时,先过2秒打印"hello world!!!",然后每隔3秒打印一次"hello world!!!"
4.SingleThreadExecutorPool
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue. (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* <tt>newFixedThreadPool(1)</tt> the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
*
* 创建一个单线程池操作共享队列,保证各个线程的执行顺序,和newFixedThreadPool(1)不同的
* 是SingleThreadExecutorPool不会开启额外的线程。即线程的执行是有序的,
*/
public class SingleThreadExecutorPoolTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int n = i;
executor.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("n====:"+n+",threadname:"+Thread.currentThread().getName());
}
});
}
executor.shutdown();
}
}
执行结果如图:
各个线程是按顺序执行的且只使用一个线程。