线程池

  • 概述

    • 就是保存多个线程对象的池子;
  • 作用

  1. 可以提升程序的运行性能;(重复利用线程,节约了频繁创建和销毁线程对象的时间)
  2. 可以保证服务器的压力;(当达到规定的上限时,可以拒绝服务)
  • 线程池接口规范

    • ExecutorService
  • 实现类

    • ThreadPoolExecutor
  • 实现类的7个参数介绍

image-20230529153815359

  • 获取线程池的两种方式
    • 自己直接new ThreadPoolExecutor(7个参数);// 这是推荐的方式,因为更安全,配置的更详细;
    • 利用工具类 Executors中的静态方法 ;(不推荐,有风险)

自己创建线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
练习使用方式1 创建线程池对象
*/
public class MyPool {
public static void main(String[] args) {
// 1: 手动创建线程池对象
ExecutorService es = new ThreadPoolExecutor(2, 3, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), new ThreadFactory() {
Random ran = new Random();
@Override
public Thread newThread(Runnable r) {
return new Thread(r,"我们自定义的线程"+ran.nextInt(100));
}
},new ThreadPoolExecutor.AbortPolicy());

System.out.println(es);

es.shutdown();
}
}

  • 线程池的常用方法

image-20230529162024934

线程池执行不带返回值的任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.itheima.demo08_ThreadPool;

import java.util.Random;
import java.util.concurrent.*;

/*
练习使用方式1 创建线程池对象
后,让线程池执行 任务
*/
public class MyPool2 {
public static void main(String[] args) {
// 1: 手动创建线程池对象
ExecutorService es = new ThreadPoolExecutor(2, 3, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), new ThreadFactory() {
Random ran = new Random();
@Override
public Thread newThread(Runnable r) {
return new Thread(r,"我们自定义的线程"+ran.nextInt(100));
}
},new ThreadPoolExecutor.AbortPolicy());

Runnable r = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+"正在处理任务中....");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"处理任务完成....");
}
};
// 使用匿名内部类的方式,提交一个任务
for (int i = 0; i < 9; i++) {
es.execute(r);
}
es.shutdown();
}
}

线程池执行带返回值的任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.itheima.demo08_ThreadPool;

import java.util.Random;
import java.util.concurrent.*;

/*
练习使用方式1 创建线程池对象
后,让线程池执行 带返回值的任务
*/
public class MyPool3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1: 手动创建线程池对象
ExecutorService es = new ThreadPoolExecutor(1, 2, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());

Callable<String> c = ()->{
String name = Thread.currentThread().getName();
System.out.println(name+"正在处理任务中...");
Thread.sleep(2000);
return name+"处理任务完成了";
};
// 使用匿名内部类的方式,提交一个任务
Future<String> f1 = es.submit(c);
Future<String> f2 = es.submit(c);
Future<String> f3 = es.submit(c);
Future<String> f4 = es.submit(c);
Future<String> f5 = es.submit(c);

String res1 = f1.get();
String res2 = f2.get();
String res3 = f3.get();
String res4 = f4.get();
String res5 = f5.get();
System.out.println(res1);
System.out.println(res2);
System.out.println(res3);
System.out.println(res4);
System.out.println(res5);

es.shutdown();
}
}

Executors工具类(了解)

  • 概述
1
可以帮我们快速创建线程池对象,但是不安全,不推荐使用;
  • 常用方法

image-20230529165512580

线程状态和转换

image-20230529165642951

当懒汉式单列设计模式遇上多线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
使用懒汉式设计单列设计模式
*/
public class A {

// 构造方法私有
private A(){

}
// 2: 提前准备一个静态的成员变量,u用于保存我们自己创建的对象,外部可以通过这个成员变量,获取对象
private static A a;

// 3: 提供一个静态方法,让别人通过这个方法,获取a对象


public static A getA() {
// 外面的判断是为了一但对象创建后,后面所有获取对象的行为都无需在经历抢锁的代码了
if(a == null){
synchronized (A.class){
// 里面的判断是为了保证刚开始前几个线程可能都会进入19行的if,为了保证安全,所以再次进行了判断
if(a==null){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
a=new A();
}
}
}
return a;
}
}