线程池
补充资料:Doug Lea (JCP组织的一人)对线程池部分贡献巨大
常用线程池的接口和类:
Executor:线程池的顶级接口
ExecutorService:线程池接口可用submit(Runnable Task)提交任务代码。包含:Shutdown;
Shutdownnow等
Executors工厂类:可以通过这一个方法得到一个线程池
NewFixedThreadPool(int n Thread):获取固定数量的线程池。参数:指线程池中线程的数量
NewCacheThreadPool()获取动态数量的线程池,无上限
对于ExecutorService:需关注实现类TheadPoolExecutor,SheduledThreadPoolExecutor
Executors:1.创建固定线程个数的线程池
2.创建缓存线程池,又任务多少来决定
3.创建单线程池
4.创建调度线程池 调度:周期、定时执行
在API中:
Shutdown:启动一次顺序关闭,执行以前提交的任务,但不接受新任务
ShutDownNow:试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表
代码示例1 固定线程个数:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo {
public static void main(String[] args) {
// 1.创建固定线程个数的线程池
ExecutorService es=Executors.newFixedThreadPool(4);
// 2.提交任务
Runnable run=new Runnable() {
private int ticket;
@Override
public void run() {
while (true) {
if (ticket <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "卖完第:" + ticket + "张票");
ticket--;
}
}
};
// 3.提交任务
for(int i=0;i<=4;i++) {
es.submit(run);
}
// 4.关闭线程池
es.shutdown();
}
}
代码示例 2 可变线程个数,由任务决定
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo {
public static void main(String[] args) {
// 1.创建固定线程个数的线程池
// ExecutorService es=Executors.newFixedThreadPool(4);
ExecutorService es2=Executors.newCachedThreadPool();
// 2.提交任务
Runnable run=new Runnable() {
private int ticket;
@Override
public void run() {
while (true) {
if (ticket <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "卖完第:" + ticket + "张票");
ticket--;
}
}
};
// 3.提交任务
for(int i=0;i<=4;i++) {
es2.submit(run);
}
// 4.关闭线程池
es2.shutdown();
}
}
注:提交任务数不一定是4.要具体看运行结果
Excutors的另外两种方法
3. ExecutorService e3=Executors.newSingleThreadExecutor();
4. ExecutorService e4=Executors.newScheduledThreadPool();
Callable接口
语法:
Public interface Callable<V>{public V call() throws Exception}
特点:有返回值;使用时需要先转化为任务后被Thread调用
代码示例:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class Demo02 {
public static void main(String[] args) {
// 功能需求:计算1-100的和并使用Callable接口
Callable<Integer> callable=new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"开始计算");
int sum = 0;
for (int j = 1;j<=100;j++){
sum+=j;
Thread.sleep(100);
}
return sum;
}
};
// 把Callable转化为可执行的任务
FutureTask<Integer> task = new FutureTask<>(callable);
// 创建线程
Thread thread = new Thread(task);
// 启动线程
thread.start();
// 获取结果
Integer sum= null;
try {
sum = task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("结果是"+sum);
}
}
Callable与线程池的结合的使用
这种方法与线程池的配合更为紧密
优点:无需先转化为task,再进行执行;无需使用匿名内部类
需求示例:使用Callable和线程池计算1-100的和
代码示例:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Demo03 {
public static void main(String[] args) throws Exception {
// 1. 创建线程池
ExecutorService es = Executors.newFixedThreadPool(1);
// 2.提交任务Future:表示将要执行任务的结果
Future<Integer> future = es.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"开始计算");
int sum=0;
for (int i=0;i<=100;i++){
sum+=i;
}
return sum;
}
});
// 3.获取任务结果
System.out.println(future.get());
// 4.关闭线程池
es.shutdown();
}
}
Future接口
功能:表示将要完成的任务的结果
案例需求:使用两个线程,并发计算1-50和51-100的和,再进行汇总统计
Future.get()方法需要等待callable的方法执行完毕才可以继续执行,即 同步
关于同步、异步:我们现在手头有两个线程A\B,A在使用过程中会调用B线程。同步的含义是例如A需要执行三个部分,在第一个部分时调用了B,调用之后不继续执行第二个部分而是等待B被调用完之后再继续执行第二第三个部分。
异步的含义是,A执行第一部分并调用了B线程,A不继续等待B线程执行完而接着执行第二部分第三部分。
代码示例:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Demo4 {
public static void main(String[] args) throws Exception{
// 1.创建线程池
ExecutorService es = Executors.newFixedThreadPool(2);
// 2.创建任务及对象
Future<Integer> future =es.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=0;i<=50;i++){
sum+=i;
}
return sum;
}
});
Future<Integer> future2=es.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=51;i<=100;i++){
sum+=i;
}
return sum;
}
});
// 3.获取结果
int sum=future.get()+future2.get();
System.out.println("结果是" + sum);
// 4.关闭线程
es.shutdown();
}
}