多线程-线程池

线程池

线程池的创建方式

一共有四种创建方式:

Executors.newCachedThreadPool(); 创建一个无限大的线程池,线程大小和任务数保持一致。
Executors.newFixedThreadPool(int xxx); 创建一个自定义线程数的线程池。如果任务大于自定义数,多余任务会暂时放在任务队列中等待空闲线程的执行。
Executors.newSingleThreadExecutor(); 创建一个线程数为1的线程池,如果任务大于1,多余任务会暂时放在任务队列中等待空闲线程的执行。
new ThreadPoolExecutor(int, int, long, ArrayBlockingQueue); 自定义线程池,第一个参数为核心线程数,第二个参数为线程池最大数,第三个参数为空闲线程存活时间,第四个参数为缓冲队列。


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPool {
	public static void main(String[] args) throws InterruptedException {
		//四种线程创建方式
		ExecutorService executorService1 = Executors.newCachedThreadPool(); //快  一个任务一个线程 线程复用
		ExecutorService executorService2 = Executors.newFixedThreadPool(10); //慢  
		ExecutorService executorService3 = Executors.newSingleThreadExecutor(); //最慢  
		ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
	
		for(int i = 0 ; i < 100 ; i++) {
			//执行线程
			executorService1.execute(new MyTest(i));
		}
		//关闭线程资源
		executorService1.shutdown();

	}
}	

class MyTest implements Runnable{
	int i = 0;
	
	public MyTest(int i) {
		this.i = i;
	}

	public void run() {
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "-->"+i++);
	}
}

线程池存在的问题:

  • newCachedThreadPool 效率高,但是创建过大线程会严重占有CPU资源,还会有内存溢出的问题。
  • newFixedThreadPool 效率低,过大任务会出现内存溢出 ,因为过多任务会先存到队列中,如果任务非常多就意味着需要足够大的内存。
  • newSingleThreadExecutor 效率最低,因为只有一个线程。会内存溢出,原因同上。

关于自定义线程的问题:

public class TestPool {
	public static void main(String[] args) throws InterruptedException {
		//创建一个拥有10个核心线程和10个非核心线程和缓存队列大小为10的线程池
		ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
	
		for(int i = 0 ; i < 100 ; i++) {
			//执行100个任务
			threadPoolExecutor .execute(new MyTest(i));
		}
		
		threadPoolExecutor .shutdown();
	}
}	

class MyTest implements Runnable{
	int i = 0;
	
	public MyTest(int i) {
		this.i = i;
	}

	public void run() {
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "-->"+i++);
	}
}

在这里插入图片描述
如图所示,只能执行前30个任务,因为我们的线程数为20,队列数为10,所以只能接收前三十个任务,后面来的任务就会拒绝掉。
但是还存在一个问题就是我们发现运行结果0-9个任务是最先执行,然后是20-29个任务被执行,10-19个任务最后执行这是为什么呢?

这就涉及到了线程的提交优先级和执行优先级的概念了。

  • 提交优先级 核心线程->任务队列->非核心线程 放不下就拒绝后面的任务
  • 执行优先级 核心线程->非核心线程->任务队列

根据优先级我们可以知道当任务进来时,首先会去给核心线程分配,所以0-9个任务被10个核心线程拿去执行了,然后10-19个任务会先放到任务队列,20-29个任务会分给非核心线程去执行。根据执行优先级是先执行核心线程然后执行非核心线程,最后执行任务队列中的,所以10-19个任务是最后执行的。
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值