池化技术
池化技术:
不直接创建具体的资源,而是创建一个池,在池里面创建具体的资源
以前是直接把任务交给具体的资源,而现在把资源交给池,池就会让空闲的资源去执行任 务,任务执行完了以后,资源并不会销毁,而是停留池里面,等待下一个任务来执行
一、线程池的好处
降低系统资源消耗,通过重用已存在的线程,降低线程创建
和销毁造成的消耗
方便线程并发数的管控
提供更强大的功能,延时定时线程池
二、常用的队列以及线程池
1.四种工作队列
(java中主要采用BlockingQueue去存储任务)
BlockingQueue :
双缓冲队列,内部使用两条队列,允许两个线程同时向队列一
个存储,一个取出操作。在保证并发安全的同时,提高了队列
的存取效率。
ArrayBlockingQueue:
采用数组实现,规定大小的BlockingQueue,其构造必须指定大
小。其所含的对象是FIFO顺序排序的。
LinkedBlockingQueue:
采用双向链表实现,大小不固定的,若其构造时指定大小,生成
的BlockingQueue有大小限制,不指定大小,其大小有
Integer.MAX_VALUE来决定。其所含的对象是FIFO顺序排序的。
PriorityBlockingQueue:
类似于LinkedBlockingQueue,但是其所含对象的排序不是
FIFO,而是依据对象的自然顺序或者构造函数的Comparator决
定。
2.常用的线程池
java一般不会自己创建线程池,因为自己创建的线程池可拓展性太低,所以java通过Executors提供四种线程池:
1.newCachedThreadPool :
创建一个可缓存线程池,如果线程池长度超过处理需要,可
灵活回收空闲线程,若无可回收,则新建线程。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NewCacheThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
//重复使用线程,一旦线程足够就不创建
//而是使用上一个任务遗留的线程去执行
//能不创建就不创建,只有迫不得已才会创建
//最多创建 0x7ffffff (2^31-1)
ExecutorService exe = Executors.newCachedThreadPool();
for (int i = 0; i < 20; i++) {
Thread.sleep(2000);
exe.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
}
}
2.newFixedThreadPool :
创建一个定长线程池,可控制线程最大并发数,超出的线程
会在队列中等待
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NewFixedThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
//线程池一旦创建,就会创建size的核心线程
//jvm不会关闭
//查看可同步线程的数量,与本代码无关
System.out.println(Runtime.getRuntime().availableProcessors());
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 20; i++) {
Thread.sleep(2000);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
}
}
3.newScheduledThreadPool :
创建一个定长线程池,支持定时及周期性任务执行
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class NewScheduledThreadPoolTest {
public static void main(String[] args) {
//还增加了延迟执行和周期性执行
ScheduledExecutorService executorService =
Executors.newScheduledThreadPool(5);
// executorService.execute(new Runnable() {
//
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName());
// }
// });
//延迟执行
// executorService.schedule(new Runnable() {
//
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName());
// }
// }, 3, TimeUnit.SECONDS);
//延迟1s执行,以后每隔2s执行一次
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}, 1, 2, TimeUnit.SECONDS);
}
}
4.newSingleThreadExecutor :
创建一个单线程化的线程池,它只会用唯一的工作线程来执
行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NewSingleThreadExecutor {
public static void main(String[] args) {
//线程池中只创建了一个线程
//这样就可以保证按顺序去执行
ExecutorService exe = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
exe.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
}
}
总结
具体使用什么线程池,还是以具体需求为主