线程池的概念:首先创建一些线程,他们的集合成为线程池,当服务器接收到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务完后不关闭该线程,而是将线程还到线程池中。
线程池的两个主要作用:
控制线程数量(避免因为创建大量的线程导致的系统崩溃)
重用线程(避免频繁地创建销毁线程)
1.
Callable 内有个 call方法可以有返回值 Runnable run方法无返回值
ExecutorService 接口继承与Executor submit方法独有返回Future
Executors 操作Executor工具类
2. ThreadPool (Executors.newFixedThreadPool(5))
public class T05_ThreadPool {
public static void main(String[] args) throws InterruptedException {
//创建固定大小的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i <= 5; i++){
fixedThreadPool.execute(() -> {try {TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println("当前运行的线程:"+ Thread.currentThread().getName());
}); }
System.out.println(fixedThreadPool);
fixedThreadPool.shutdown();
System.out.println(fixedThreadPool.isTerminated());
System.out.println(fixedThreadPool.isShutdown());
TimeUnit.SECONDS.sleep(5);
System.out.println(fixedThreadPool.isTerminated());
System.out.println(fixedThreadPool.isShutdown());
System.out.println(fixedThreadPool); }}
3. FutureTaskPool
public class T06_FutureTaskPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask futureTask = new FutureTask(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return 10086;}); //内部是Callable中call方法
new Thread(futureTask).start(); //启动线程
System.out.println(futureTask.get()); //该方法是一个阻塞方法 执行结束该线程才完成
System.out.println("***************************************");
//创建线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
Future submit = fixedThreadPool.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return 10010;});
fixedThreadPool.shutdown();
System.out.println(submit.get());
System.out.println(submit.isDone());
System.out.println(submit.isCancelled()); }}
4. ParallelComputing //并行执行
public class T07_ParallelComputing {
//计算1000000以内的质数
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ArrayList integers = get(1, 1000000);
long end = System.currentTimeMillis();
System.out.println(end - start);
//创建Callable线程实现
MyTask myTask = new MyTask(1, 20000);
MyTask myTask1 = new MyTask(200001, 400000);
MyTask myTask2 = new MyTask(400001, 600000);
MyTask myTask3 = new MyTask(600001, 800000);
MyTask myTask4 = new MyTask(800001, 1000000);
ExecutorService pool = Executors.newFixedThreadPool(5);
Future> submit = pool.submit(myTask);
Future> submit1 = pool.submit(myTask1);
Future> submit2 = pool.submit(myTask2);
Future> submit3 = pool.submit(myTask3);
Future> submit4 = pool.submit(myTask4);
start = System.currentTimeMillis();
submit.get();
submit1.get();
submit2.get();
submit3.get();
submit4.get();
end = System.currentTimeMillis();
System.out.println(end - start);
pool.shutdown(); }
static class MyTask implements Callable> {
int start, end;
public MyTask(int start, int end) {
this.start = start;
this.end = end; }
@Override
public List call() throws Exception {
return get(start, end);} }
public static boolean isPrime(int num) {
for (int i = 2; i <= num / 2; i++)
if (num % 2 == 0) return false;
return true;}
public static ArrayList get(int start, int end) {
ArrayList arrayList = new ArrayList<>();
for (int i = start; i <= end; i++) {
if (isPrime(i)) arrayList.add(i); }
return arrayList; }}
5. CachedPool
缓存线程池(Executors.newCachedThreadPool()),当有任务来线程池无空闲线程就会创建(默认无上限),但可以设置,默认当执行完的线程空闲60S自动关闭
public class T08_CachedPool {
public static void main(String[] args) throws InterruptedException {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
System.out.println(cachedThreadPool);
for (int i = 0; i < 3; i++)
{cachedThreadPool.execute(() -> System.out.println(Thread.currentThread().getName())); }
System.out.println(cachedThreadPool);
TimeUnit.SECONDS.sleep(70);
System.out.println(cachedThreadPool);
cachedThreadPool.shutdown(); }}
6. SinglePool (Executors.newSingleThreadExecutor()) 线程池内就一个线程
7.ScheduledPool (Executors.newScheduledThreadPool(3))
public class T10_ScheduledPool {
public static void main(String[] args) {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
//定时执行的线程池,有四个参数:接口,初始延迟,执行期间,时间单位
pool.scheduleAtFixedRate(() -> {
try { TimeUnit.MILLISECONDS.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(Thread.currentThread().getName());
},0,300, TimeUnit.MILLISECONDS); }
}
8.WorkStealingPool (Executors.newWorkStealingPool()) 窃取
该线程池,每个线程都维护自己的任务队列,当执行完自己队列里面的线程 会去偷其他线程内的任务执行
可以传int 参数,默认不传根据CPU核数启动线程数
这是个精灵线程 daemo,内部是封装的 ForkJoinPool
9. ForkJoinPool 下面两个都是递归的思想 进行拆分
RecursiveAction //无返回值
RecursiveTask //有返回值
[例子如下 T12_ForkJoinPool ]
public class T12_ForkJoinPool {
static int[] nums = new int[100000];
static int maxNum = 5000;
static Random random = new Random();
static {
//初始化数组
for (int i = 0; i < nums.length; i++) nums[i] = random.nextInt(100);
System.out.println(Arrays.stream(nums).sum());
}
public static void main(String[] args) throws Exception {
ForkJoinPool joinPool = new ForkJoinPool();
/* MyTask task = new MyTask(0, nums.length);
joinPool.execute(task); //无返回值
System.out.println("*******************************");
*/
MyTask2 task2 = new MyTask2(0, nums.length);
ForkJoinTask joinTask = joinPool.submit(task2);
System.out.println(joinTask.get()); //有返回值
joinPool.shutdown();
//System.in.read(); //因为是守护线程会在后台运行
}
static class MyTask extends RecursiveAction {
int start, end;
public MyTask(int start, int end) {
this.start = start;
this.end = end; }
@Override
protected void compute() {
//递归切分逻辑
if (end - start <= 5000) {
long sum = 0;
for (int i = start; i < end; i++) sum += nums[i];
System.out.println("start:" + start + " end:" + end + " sum:" + sum);
} else {
int middle = start + (end - start) / 2;
MyTask task1 = new MyTask(start, middle);
MyTask task2 = new MyTask(middle, end);
task1.fork();
task2.fork(); }}}
static class MyTask2 extends RecursiveTask {
int start, end;
public MyTask2(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
//递归切分逻辑
if (end - start <= 5000) {
long sum = 0;
for (int i = start; i < end; i++) sum += nums[i];
return sum; }
else {
int middle = start + (end - start) / 2;
MyTask2 task1 = new MyTask2(start, middle);
MyTask2 task2 = new MyTask2(middle, end);
task1.fork();
task2.fork();
return task1.join() + task2.join(); }}}}