Java中有几种线程池?使用线程池有什么风险?

Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具,它真正的线程池接口是ExecutorService。

使用线程池能够为了防止资源不足,因为频繁创建和销毁线程会消耗大量资源,尤其是当线程执行时间>线程创建时间+线程销毁时间,此时会堆积大量线程。Java中,创建线程池有四种方式,如下:

1)newCachedThreadPool()
创建一个可缓存线程池,线程池为无限大,如果线程池长度超过处理需要,可灵活回收空闲线程,即当执行当前任务时上一个任务已经完成,会复用执行上一个任务的线程,而不用每次新建线程;如果上一个线程没有结束则会新建线程。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CachedThreadPool {
	private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

	public static void main(String args[]) {
		for (int i = 0; i < 10; i++) {
			try {
				if (i == 4) {
					Thread.sleep(2000);
				}
			} catch (Exception e) {
				e.getStackTrace();
			}
			cachedThreadPool.execute(new Runnable() {
				public void run() {
					try {
						Thread.sleep(1000);
					} catch (Exception e) {
						e.getStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在被执行");
				}
			});
		}
	}
	/**
	 * 执行结果如下(console输出): 
	 * pool-1-thread-1正在被执行 
	 * pool-1-thread-4正在被执行
	 * pool-1-thread-3正在被执行 
	 * pool-1-thread-2正在被执行 
	 * pool-1-thread-4正在被执行
	 * pool-1-thread-1正在被执行 
	 * pool-1-thread-3正在被执行 
	 * pool-1-thread-2正在被执行
	 * pool-1-thread-5正在被执行 
	 * pool-1-thread-6正在被执行
	 */
}

在i=5的时候,需停留2秒,此时线程1-4都已经释放,所以1-4线程可以复用,这就是newCachedThreadPool()线程池的优点。

2)newFixedThreadPool()
可重用固定个数的线程池,当当前线程数大于总线程数时会进行等待,等待线程池内的线程执行完,相对来说占用内存少,因为如果等待线程数量过多,也是相对耗废资源的。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FixedThreadPool {
	private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);

	public static void main(String args[]) {
		for (int i = 0; i < 10; i++) {
			fixedThreadPool.execute(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "正在被执行");
					try {
						Thread.sleep(1000);
					} catch (Exception e) {
						e.getStackTrace();
					}
				}
			});
		}
	}
}

线程池大小为4,所以如果线程执行数量超过4则会进行等待,所以newFixedThreadPool()的缺点也很明显,就是如果线程池数量设置明显过小,则会导致大量线程等待,造成资源浪费。

3)newSingleThreadExecutor()
单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO,优先级)执行,如果该线程异常结束,会有另一个线程取代它,保证顺序执行。
所以缺点也很明显,就是单线程执行,线程多,执行速度会比较慢。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadPool {
	private static ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

	public static void main(String args[]) {
		for (int i = 0; i < 10; i++) {
			final int index = i;
			singleThreadPool.execute(new Runnable() {
				public void run() {
					try {
						System.out.println(Thread.currentThread().getName() + "正在执行 index=" + index);
						Thread.sleep(1000);
					} catch (Exception e) {
						e.getStackTrace();
					}
				}
			});
		}
	}
	/**
	 * 执行结果如下: 
	 * pool-1-thread-1正在执行 index=0 
	 * pool-1-thread-1正在执行 index=1
	 * pool-1-thread-1正在执行 index=2 
	 * pool-1-thread-1正在执行 index=3
	 * pool-1-thread-1正在执行 index=4 
	 * pool-1-thread-1正在执行 index=5
	 * pool-1-thread-1正在执行 index=6 
	 * pool-1-thread-1正在执行 index=7
	 * pool-1-thread-1正在执行 index=8 
	 * pool-1-thread-1正在执行 index=9
	 * 
	 * 结论:所有的线程都是线程1来执行而且是有序执行,这就是单线程池!
	 */
}

4)newScheduledThreadPool()
可重用固定个数的线程池,当前线程数大于总数则会进行等待,并且可以设置线程延迟执行时间。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPool {
	private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);

	public static void main(String args[]) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmsssss");

		for (int i = 0; i < 10; i++) {
			System.out.println(i + "开始执行时间" + sdf.format(new Date()));
			scheduledThreadPool.schedule(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "正在执行 执行时间=" + sdf.format(new Date()));
				}
			}, 3, TimeUnit.SECONDS);
		}
	}
}

那么,使用线程池有没有什么风险呢?

1)死锁:任何的多线程都有可能发生死锁的风险(线程之间互相等待)

2)资源不足:线程池太大造成,正常来说合理创建线程池大小一般不会出现这个问题

3)线程泄漏和请求过载
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章