Java学习笔记---多线程之线程池

线程池

概念:

当对程序有请求时,程序创建线程去处理该请求,若每有一个请求就创建一个线程去处理,处理完毕后又销毁,那么请求不断时,创建、销毁就会不断重复,这对资源是一种浪费,时间上也会有浪费。线程池技术,就是先创建一个“池”,里面已经创建好合适量的线程,当有任务请求时,重复利用已有线程,减少了不断创建销毁这个过程的开销,同时,因为线程处于已经创建的转态,当有任务来时,可以直接开始执行请求,节省了线程创建时消耗时间(虽然时间好像很少,但是量变引起质变),使应用程序响应更快。

  • 一个简单的线程池该有的东西
    • 线程池管理器
      • 创建、销毁并管理线程池,将工作线程放入线程池中
    • 工作线程
      • 一个可以循环执行任务的线程,没有任务时就是处于等待状态
    • 任务队列
      • 将没有处理的任务放在任务队列中
    • 任务接口
      • 每个任务必须实现的接口,主要用来规定任务的入口、任务完成后的收尾工作、任务的执行状态等等,工作线程通过该接口调度任务的执行

举个例子–简单的线程池应用

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ExecutorServiceTest {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		testFixPool();
		testSchPool();
		testSchePool();
	}
	
	//第一个方法
	private static void testFixPool() throws InterruptedException, ExecutionException {
		//newFixedThreadPool()---创建一个线程池,重用固定数量的线程,从共享无界队列中运行,使用提供的ThreadFactory在需要时创建新线程。
		//这里的newFixedThreadPool()中的x是表示一个值,创建x个线程,请自己根据自己需要写入参数
		ExecutorService service = Executors.newFixedThreadPool(x);
		for (int i = 0; i < 5; i++) {
			Future<?> future = service.submit(() -> {
				String name = Thread.currentThread().getName();
				System.out.println(name + "正在执行任务...");
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			});
			System.out.println("得到结果:" + future.get());
		}
		service.shutdown();
	}
	//第二个方法
	private static void testSchPool() throws InterruptedException, ExecutionException {
		//newScheduledThreadPool()---创建一个线程池,可以调度命令在给定的延迟之后运行,或定期执行。
		//这里的newScheduledThreadPool()中的x是表示一个值,创建x个线程,请自己根据自己需要写入参数
		ExecutorService service = Executors.newScheduledThreadPool(x);
		for (int i = 0; i < 7; i++) {
			Future<?> future = service.submit(() -> {
				String name = Thread.currentThread().getName();
				System.out.println(name + "正在执行任务...");
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			});
			System.out.println("得到结果:" + future.get());
		}
		service.shutdown();
	}
	//第三个方法
	private static void testSchePool() throws InterruptedException, ExecutionException {
		ExecutorService service = Executors.newScheduledThreadPool(2);
		Set<Callable<Integer>> tasks = new HashSet<>();
		tasks.add(()->{
			String name = Thread.currentThread().getName();
			for (int i = 0; i < 3; i++) {
				System.out.println(name+"搬的"+(i+1)+"块转...");
				TimeUnit.SECONDS.sleep(1);
			}
			return 1;
		});
		tasks.add(()->{
			String name = Thread.currentThread().getName();
			for (int i = 0; i < 3; i++) {
				System.out.println(name+"吃的第"+(i+1)+"块西瓜...");
				TimeUnit.SECONDS.sleep(1);
			}
			return 2;
		});
		tasks.add(()->{
			String name = Thread.currentThread().getName();
			for (int i = 0; i < 3; i++) {
				System.out.println(name+"打的第"+(i+1)+"万行代码...");
				TimeUnit.SECONDS.sleep(1);
			}
			return 3;
		});
		
		List<Future<Integer>> result = service.invokeAll(tasks);
		for (Future<Integer> future : result) {
			System.out.println("线程任务执行结果:"+future.get());
		}
		service.shutdown();
	}
}
  • 第一个方法执行

    • 创建2个线程运行结果:
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null

    • 创建5个线程运行结果:
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-3正在执行任务…
      得到结果:null
      pool-1-thread-4正在执行任务…
      得到结果:null
      pool-1-thread-5正在执行任务…
      得到结果:null

    • 创建6个线程运行结果:
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-3正在执行任务…
      得到结果:null
      pool-1-thread-4正在执行任务…
      得到结果:null
      pool-1-thread-5正在执行任务…
      得到结果:null

  • 第二个方法执行

    • 创建3个线程运行结果:
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-3正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null

    • 创建建7个线程运行结果:
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-3正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-4正在执行任务…
      得到结果:null

    • 创建9个线程运行结果:
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-1正在执行任务…
      得到结果:null
      pool-1-thread-3正在执行任务…
      得到结果:null
      pool-1-thread-2正在执行任务…
      得到结果:null
      pool-1-thread-4正在执行任务…
      得到结果:null

  • 第三个方法执行

    • 创建2个线程运行结果:
      pool-1-thread-1打的第1万行代码…
      pool-1-thread-2吃的第1块西瓜…
      pool-1-thread-1打的第2万行代码…
      pool-1-thread-2吃的第2块西瓜…
      pool-1-thread-1打的第3万行代码…
      pool-1-thread-2吃的第3块西瓜…
      pool-1-thread-1搬的1块转…
      pool-1-thread-1搬的2块转…
      pool-1-thread-1搬的3块转…
      线程任务执行结果:3
      线程任务执行结果:2
      线程任务执行结果:1
    • 创建3个线程运行结果:
      pool-1-thread-2打的第1万行代码…
      pool-1-thread-1吃的第1块西瓜…
      pool-1-thread-3搬的1块转…
      pool-1-thread-2打的第2万行代码…
      pool-1-thread-1吃的第2块西瓜…
      pool-1-thread-3搬的2块转…
      pool-1-thread-1吃的第3块西瓜…
      pool-1-thread-2打的第3万行代码…
      pool-1-thread-3搬的3块转…
      线程任务执行结果:3
      线程任务执行结果:2
      线程任务执行结果:1
    • 创建5个运行结果:
      pool-1-thread-1打的第2万行代码…
      pool-1-thread-3吃的第2块西瓜…
      pool-1-thread-2搬的2块转…
      pool-1-thread-1打的第3万行代码…
      pool-1-thread-3吃的第3块西瓜…
      pool-1-thread-2搬的3块转…
      线程任务执行结果:3
      线程任务执行结果:2
      线程任务执行结果:1

Executors中不同的方法创建的线程,执行任务时会略有不同,结果如上所示。

合理利用进程池(合理利用多线程)
如有错误,欢迎指正。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值