什么是线程池?
等待池是一个存放等待线程的池子,而线程池也就是一个存放线程的池子,我们可以提前创建好一些线程,当我们有任务的时候去线程池里面拿线程来执行任务,任务执行完成之后又放回线程池
为什么要使用线程池?
- 使用线程池的原因是因为当我们有很多线程的时候,我们频繁的创建和销毁线程会给我们造成很大的资源开销
- 线程并发数量过多,抢占系统资源从而导致阻塞
- 方便我们对线程进行管理
线程池
Executor是线程池的顶级接口,Java通过Executors提供了四种线程池,这四种线程池都是直接或间接配置ThreadPoolExecutor的参数实现的。
- FixedThreadPool() 固定长度的线程池。可以控制线程的最大并发数
- CachedThreadPool() 可缓存线程池。线程数无限制,即有空闲线程则复用空闲线程,若无空闲线程则新建线程。
- SingleThreadExecutor() 只有一个线程的单线程池。主要是为了实现串行
- ScheduledThreadPool() 定时或周期性执行任务的线程池。
创建线程池的时候,上面三个线程池使用ExecutorService接口,并使用Executors实现类来创建一个线程池
创建定时线程池时,使用ScheduledExecutorService接口,并通过new一个ScheduledThreadPoolExecutor实现类来创建
package experiment;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
class Person extends Thread{
@Override
public void run() {
System.out.println("买东西...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
}
}
public class B {
public static void main(String[] args) {
ExecutorService executor= Executors.newFixedThreadPool(3);
Person person=new Person();
executor.submit(person);
executor.submit(person);
}
}
运行结果如下:
可以看到我们直接启动了两个线程,需要注意的是,但我们的任务数超过我们线程池里面的长度时,系统会拿出所有的线程来执行任务,执行完成之后会再去执行没有执行的任务
使用定时线程池的时候跟其他的线程池不同
package experiment;
import java.util.concurrent.*;
class Person extends Thread{
@Override
public void run() {
System.out.println("买东西...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
}
}
public class B {
public static void main(String[] args) {
ScheduledExecutorService sch=new ScheduledThreadPoolExecutor(3);
Person person=new Person();
sch.schedule(person,2, TimeUnit.SECONDS);
sch.schedule(person,3, TimeUnit.SECONDS);
}
}
运行结果:
任务一是在2s之后运行的,任务二是在3s之后运行的,也就是任务一执行之后的1s之后
schedule的参数:参数一是任务,参数二是延迟时间,参数三是时间单位
另外再说一下就是,当我们的任务都执行完毕的时候,我们的程序并没有结束执行,因为我们的线程池还没有关闭,想要关闭可以使用shutdown() 方法
说一个问题就是,如果我们设定了定时任务,但是我们又关闭了线程池,这个时候其实定时任务仍然会执行
package experiment;
import java.util.concurrent.*;
class Person extends Thread{
@Override
public void run() {
System.out.println("买东西...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
}
}
public class B {
public static void main(String[] args) {
ScheduledExecutorService sch=new ScheduledThreadPoolExecutor(3);
Person person=new Person();
sch.schedule(person,2, TimeUnit.SECONDS);
sch.schedule(person,3, TimeUnit.SECONDS);
sch.shutdown();
System.out.println("任务结束");
}
}
解决方法是使用isTerminated
isTerminted() 调用shutdown关闭线程池后,并且所有的任务都执行完毕后返回true
package experiment;
import java.util.concurrent.*;
class Person extends Thread{
@Override
public void run() {
System.out.println("买东西...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
}
}
public class B {
public static void main(String[] args) {
ScheduledExecutorService sch=new ScheduledThreadPoolExecutor(3);
Person person=new Person();
sch.schedule(person,2, TimeUnit.SECONDS);
sch.schedule(person,3, TimeUnit.SECONDS);
sch.shutdown();
while(sch.isTerminated()){
System.out.println("任务结束");
}
}
}
有任何不对的地方,欢迎联系改正!!!感谢阅读