线程池
使用线程池(详细查看JDK文档)
- 背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大;
- 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具;
- 好处:
- 提高响应速度(减少了创建新线程的时间)
- 降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
- 便于线程管理(…)
-
corePoolSize:
核心池的大小 -
maximumPoolSize:
最大线程数 -
keepAliveTime:
线程没有任务时保持多长时间后会终止
-
-
JDK 5.0
起提供了线程池相关API:ExecutorService和Executors
-
ExecutorService:
真正的线程池接口。常见的子类ThreadPoolExecutor
void execute(Runnable command)
:执行任务/命令,没有返回值,一般用来执行Runnable
-
<T> Future<T> submit(Callable<T> task):
执行任务,有返回值,一般又来执行Callable -
void shutdown():
关闭连接池;
-
Executors:
工具类、线程池的工厂类,用于创建并返回不同类型的线程池;
代码实现:没有返回值的(执行Runnable)
// 测试线程池
public class TestThreadExecutor {
public static void main(String[] args) {
// 步骤一:创建服务,创建线程池
//newFixedThreadPool 参数为:线程池的大小
ExecutorService service = Executors.newFixedThreadPool(10);
// 步骤二:执行线程
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
// 步骤三:关闭线程池
service.shutdown();
}
}
class MyThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
执行结果:
pool-1-thread-1
pool-1-thread-4
pool-1-thread-3
pool-1-thread-2
pool-1-thread-5
代码实现:有返回值Callable<返回值>
// 实现Callable<返回值>()接口--实现多线程下载图片
public class TestCallable implements Callable<Boolean> {//<返回值类型>
private String url;// 网络图片地址
private String name;// 保存的文件名
// 构造器
public TestCallable(String url,String name){// 构造器是对本类的构造,名字必须一致
this.url = url;
this.name = name;
}
// 下载图片线程的执行体
@Override
public Boolean call() {
WebDownloader3 webDownloader = new WebDownloader3();
webDownloader.downloader(url,name);
System.out.println("下载的文件名为:" + name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 图片路径在网上随便找一个
TestCallable t1 = new TestCallable("https://www.icode9.com/i/ll/?i=48a7e900dbbe409585fe118a293f74df.png","1.jpg");
TestCallable t2 = new TestCallable("https://www.icode9.com/i/ll/?i=48a7e900dbbe409585fe118a293f74df.png","2.jpg");
TestCallable t3 = new TestCallable("https://www.icode9.com/i/ll/?i=48a7e900dbbe409585fe118a293f74df.png","3.jpg");
/*
1. 开启执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
2. 提交执行:Future<Boolean> result1 = ser.submit(t1);
3. 获取结果:boolean b1 = result1.get();
4. 关闭服务:ser.shutdownNow();
*/
// (1)创建执行服务:【ExecutorService与Executors后面详细讲解】
ExecutorService ser = Executors.newFixedThreadPool(3);
// (2)提交执行
Future<Boolean> result1 = ser.submit(t1);
Future<Boolean> result2 = ser.submit(t2);
Future<Boolean> result3 = ser.submit(t3);
// (3)获取结果
boolean b1 = result1.get();
boolean b2 = result2.get();
boolean b3 = result3.get();
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
// (4)关闭服务
ser.shutdownNow();
}
}
// 下载器
class WebDownloader3{
// 下载方法
public void downloader(String url,String name){
// 使用Commons-io包中的方法进行操作
try {
// FileUtils-文件工具
FileUtils.copyURLToFile(new URL(url),new File(name));// 将网页地址拷贝成文件
} catch (IOException e) {
e.printStackTrace();
System.out.println("Io异常,download方法异常!");
}
}
}
总结:线程实现的方式
// 总结:线程实现的方式
public class ThreadStyle {
public static void main(String[] args) {
// 方式1
new MyThread1().start();
// 方式2
new Thread(new MyThread2()).start();
// 方式3
FutureTask<Integer> future = new FutureTask<Integer>(new MyThread3());
new Thread(future).start();
try {
Integer integer = future.get();
System.out.println("方式3获取的返回值:" + integer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
// 1.继承Thread类
class MyThread1 extends Thread{
@Override
public void run() {
System.out.println("MyThread1");
}
}
// 2.实现了Runnable接口
class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("MyThread2");
}
}
// 3.实现了Callable<V>接口
class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("MyThread3");
return 520;
}
}
执行结果:
MyThread1
MyThread2
MyThread3
方式3获取的返回值:520