目录
- 1.为什么要使用线程池
- 2.线程池的组成部分
- 3.线程池适合应用的场合
- 4.Java内置线程池
- 5.匿名内部类的方式实现多线程程序
- 6.定时器
1.为什么要使用线程池
在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务,这就是“池化资源”技术产生的原因。
线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。
2.线程池的组成部分
一个比较简单的线程池至少应包含线程池管理器、工作线程、任务列队、任务接口等部分。其中线程池管理器的作用是创建、销毁并管理线程池,将工作线程放入线程池中;工作线程是一个可以循环执行任务的线程,在没有任务是进行等待;任务列队的作用是提供一种缓冲机制,将没有处理的任务放在任务列队中;任务接口是每个任务必须实现的接口,主要用来规定任务的入口、任务执行完后的收尾工作、任务的执行状态等,工作线程通过该接口调度任务的执行。
线程池管理器至少有下列功能:创建线程池,销毁线程池,添加新任务。
工作线程是一个可以循环执行任务的线程,在没有任务时将等待。任务接口是为所有任务提供统一的接口,以便工作线程处理。任务接口主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等。
3.线程池适合应用的场合
当一个服务器接受到大量短小线程的请求时,使用线程池技术是非常合适的,它可以大大减少线程的创建和销毁次数,提高服务器的工作效率。但是线程要求的运动时间比较长,即线程的运行时间比
4.Java内置线程池
线程池概述
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。
而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池
内置线程池的使用概述
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool(): 根据任务的数量来创建线程对应的线程个数
public static ExecutorService newFixedThreadPool(int nThreads): 固定初始化几个线程
public static ExecutorService newSingleThreadExecutor(): 初始化一个线程的线程池
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池
根据任务的数量来创建线程对应的个数
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* GEEK
* Description:爱学Java
* @author :LiGer
*/
public class Test1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i+"爱学Java");
}
}
});
executorService.shutdown();
}
}
固定初始化几个线程
public class MyTest2 {
public static void main(String[] args) {
// 固定初始化几个线程
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"=="+i);
}
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "==" + i);
}
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "==" + i);
}
}
});
executorService.shutdown();
}
}
初始化一个线程的线程池
import java.util.concurrent.*;
/**
* GEEK
* Description:爱学Java
* @author :LiGer
*/
public class Test2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 0; i < 100; i++) {
sum+=i;
}
return sum;
}
};
Future<Integer> submit = executorService.submit(callable);
Integer integer = submit.get();
System.out.println(integer);
}
}
5.匿名内部类的方式实现多线程程序
new Thread( ){ 代码…}.start ( );
new Thread(new Runnable( ){ 代码… }).start( );
/**
* GEEK
* Description:爱学Java
* @author :LiGer
*/
public class Test3 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Java程序开始执行了");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我是另一个Java程序");
}
}).start();
}
}
6.定时器
定时器是一个应用十分广泛的线程工具,可用于调度多个定时任务以后台线程的方式执行。
在Java中,可以通过Timer和TimerTask类来实现定义调度的功能。
Timer和TimerTask
Timer:
public Timer()
public void schedule(TimerTask task, long delay):
public void schedule(TimerTask task,long delay,long period);
public void schedule(TimerTask task, Date time):
public void schedule(TimerTask task, Date firstTime, long period):
TimerTask:定时任务
public abstract void run()
public boolean cancel()
开发中
Quartz是一个完全由java编写的开源调度框架。
定时器案例演示
import java.util.Timer;
import java.util.TimerTask;
/**
* GEEK
* Description:爱学Java
* @author :LiGer
*/
public class Test4 {
public static void main(String[] args) {
Timer timer = new Timer();
MyTimerTask myTimerTask = new MyTimerTask(timer);
timer.schedule(myTimerTask,3000);
}
}
class MyTimerTask extends TimerTask {
private Timer timer;
public MyTimerTask(Timer timer) {
this.timer = timer;
}
@Override
public void run() {
System.out.println("boom~~~");
System.out.println("定时炸弹爆炸了");
timer.cancel();//关闭定时器
}
}