标签:工厂方法 except HERE 情况下 第一个 容器 executors http link
系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互,在这种情况下,使用线程池可以很好地提高性能。
线程池的模式很像生产者消费者模式,消费的对象是一个一个的能够运行的任务。
1、准备一个任务容器。
2、一次性启动10个消费者线程。
3、刚开始任务容器是空的,所以线程都wait在上面。
4、直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒。
5、这个消费者线程取出“任务”,并且执行这个任务,执行完毕后,继续等待下一次任务的到来。
6、如果短时间内,有较多的任务加入,那么就会有多个线程被唤醒,去执行任务。
public class ThreadPool {
int threadPoolSize;
//任务队列
LinkedList<Runnable> tasks=new LinkedList<>();
public ThreadPool() {
threadPoolSize=10;
synchronized (tasks) {
for (int i=0;i<threadPoolSize;i++) {
new TaskConsumerThread("任务消费者线程"+i).start();
}
}
}
public void add(Runnable runnable) {
synchronized (tasks) {
tasks.add(runnable);
tasks.notifyAll();
}
}
class TaskConsumerThread extends Thread {
public TaskConsumerThread(String name) {
super(name);
}
public void run() {
System.out.println("启动:" + this.getName());
Runnable task;
while (true) {
synchronized (tasks) {
while (tasks.isEmpty()) {
try {
tasks.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
task=tasks.removeLast();
tasks.notifyAll();
}
System.out.println(this.getName() + "获取到任务,并执行");
task.run();
}
}
}
}
下面是一个测试
class TestThread{
public static void main(String[] args) {
ThreadPool pool=new ThreadPool();
for (int i=0;i<5;i++) {
Runnable task=new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行任务");
}
};
pool.add(task);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
启动:任务消费者线程0
任务消费者线程0获取到任务,并执行
任务消费者线程0正在执行任务
启动:任务消费者线程1
启动:任务消费者线程2
启动:任务消费者线程3
启动:任务消费者线程4
启动:任务消费者线程5
启动:任务消费者线程6
启动:任务消费者线程7
启动:任务消费者线程8
启动:任务消费者线程9
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
在Java5之前,开发者必须手动实现自己的线程池;从Java5开始,Java内建支持线程池,新增一个Executors工厂类来产生线程池,该工厂类包含如下几个静态的工厂方法来创建线程池:
ExecutorService代表尽快执行线程的线程池,程序只要将一个Runnable对象或Callable对象提交给该线程池(submit方法),该线程池就会尽快执行该任务。
用完一个线程池后,应该调用该线程池的shutdown()方法,该方法将启动线程池的关闭序列,调用shutdown()方法后的线程池不再接收新任务。
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。
ExecutorService executorService= Executors.newFixedThreadPool(3);
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("第一个线程池执行第一个线程任务");
}
});
executorService.shutdown();
ScheduledExecutorService scheduledExecutorService=Executors.newScheduledThreadPool(3);
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("第二个线程池执行第一个线程任务");
}
},10, TimeUnit.SECONDS);
scheduledExecutorService.shutdown();
使用线程池优点总结:
1、系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互,在这种情况下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短的线程时,应该使用线程池。
2、使用线程池可以有效地控制系统中并发线程的数量,当系统中包含大量并发线程时,会导致系统性能剧烈下降,甚至导致JVM崩溃,而线程池的最大线程数参数可以控制系统中并发线程数量。
3、能够对线程进行简单的管理,并提供定时执行、间隔执行等功能。
参考:HowtoJ
标签:工厂方法 except HERE 情况下 第一个 容器 executors http link
原文地址:https://www.cnblogs.com/sqmax/p/9690311.html