1.线程池的概念
线程池的思想:当我们使用线程的时候,就去线程池里获取一个线程来使用,使用完成之后不会销毁,而是可以继续去执行其他的任务
我们之前都是在需要线程的时候去创建一个线程,这样使用非常方便,但是如果并发的线程数量很多的话,每个线程都可能就执行很短的时间就结束了,那么,这样频繁的创建线程就会大大的降低系统的效率,因为频繁创建和销毁线程需要时间
所以我们需要【线程池】
其实就是一个容纳很多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程的操作,无需反复创建线程而消耗过多的资源
2.线程池的使用
真正的线程池接口是 Java.util.concurrent.ExecutorService 是一个接口
Java.util.concurrent.Executors 线程工厂类里面提供了一些静态方法,生成一些常用的线程池
Executors 类中有个创建线程池的方法:
- public static ExecutorService newFixedThreadPool(int nThreads): 创建指定数量的线程的线程池
那么,如何提交任务到线程池,并执行任务: ExecutorService 线程池的方法:
- public Future<?> submit(Runnable task): 获取线程池中的某一个线程对象,并执行任务,运行run()方法
- <T> Future<T> submit(Callable<T> task): 获取线程池中的某一个线程对象,并执行任务
- Future ---> 用来封装线程任务执行后的返回值
V get(): 可以获取封装的返回值
- Callable<V>接口:
- V call() throws Exception
线程池的使用步骤:
1.创建线程池,初始化线程
2.创建任务
3.提交任务,并执行任务
4.销毁线程池(一般开发中不会执行)
MyRunnable类
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"任务开始...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"任务结束...");
}
}
MyCallable类
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+"任务开始");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"任务结束");
return "donglan" ;
}
}
Tests类
public class Tests {
public static void main(String[] args) {
// 1.创建线程池,初始化两条线程
ExecutorService pools = Executors.newFixedThreadPool(1);
// 2.创建任务
MyRunnable mr = new MyRunnable();
// 提交任务,执行任务
pools.submit(mr);
pools.submit(mr);
pools.submit(mr);
pools.submit(mr);
pools.submit(mr);
// 4.销毁线程池 开发项目一般不用
pools.shutdown();
}
}
Tests_Callable类
public class Tests_Callable {
public static void main(String[] args) {
// 1.创建线程池,初始化两条线程
ExecutorService pools = Executors.newFixedThreadPool(2);
// 2.创建任务
MyCallable mc = new MyCallable();
// 任务提交,任务执行
pools.submit(mc);
pools.submit(mc);
pools.submit(mc);
pools.submit(mc);
pools.submit(mc);
Future<String> f = pools.submit(mc);
try {
System.out.println(f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// 4.销毁线程池 开发项目一般不适用
pools.shutdown();
}
}
3.线程池的练习
需求: 使用线程池的方式执行任务,返回 1~n 的和
MyCallable类
public class MyCallable implements Callable<Integer>{
int n ;
public MyCallable(int n) {
this.n = n;
}
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"在执行任务");
int sum = 0;
for (int i = 1; i <= n; i++) {
sum +=i;
}
System.out.println(Thread.currentThread().getName()+"结束任务");
return sum;
}
}
Tests类
public class Tests {
public static void main(String[] args) {
// 1.创建线程池,初始化两条线程
ExecutorService pool = Executors.newFixedThreadPool(2);
// 2.创建任务
MyCallable mc = new MyCallable(100);
// 提交任务,执行任务
Future<Integer> f = pool.submit(mc);
try {
System.out.println("累加和为:"+f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// 4.销毁线程池 开发项目一般不使用
pool.shutdown();
}
}