4-线程池

线程池的基本思想

创建线程对象和清除线程垃圾都会大量占用CPU等系统资源,使用线程池就可以很好的解决资源浪费的问题。

线程池的基本思想:
在系统中开辟一块区域,存放一些待命的线程,这个区域成为线程池。
如果有需要执行的任务,则从线程池中借一个待命的线程来执行指定的任务,任务执行结束在将借的线程归还
这样就避免了大量创建线程对象,浪费CPU、内存资源的问题。

常用线程池类型

固定尺寸的线程池:待命线程的数量是一定,创建线程池后不能改变
优点:实现简单
缺点:
如果要执行的任务数量很多,超过待命线程的数量,有可能造成大量的等待
如果要执行的任务数量很少,大量待命的线程也可能造成内存的浪费

可变尺寸的线程池:待命线程的数量根据任务负载的需要动态变化
优点:
如果等待执行的任务数量很多,系统会自动扩充待命线程的数量,来提高效率
如果等待执行的任务数量很少,系统会自动缩减待命线程的数量,来减少内存消耗
缺点:实现复杂

固定尺寸线程池

创建线程池
获取固定线程池的方法,使用Executors类的静态工厂方法创建线程池:

public static ExecutorService newFixedThreadPool(int nThreads)
创建一个具有固定大小的线程池,如果线程异常终止,将产生新的线程来替代它

public static ExecutorService newSingleThreadExecutor()
创建一个线程池,在同一时刻只可以执行一个任务,使用这个方法可以保证多个任务顺序执行,并且不可以被重新配置为支持多个线程,如果该线程异常终止,将产生新的线程来替代它

两个方法返回的都是ExecutorService接口类型的引用,指向线程池对象,使用它的execute方法使用线程池中的线程执行指定的任务
void execute(Runnable command)

关闭线程池
使用线程池的程序在所有任务结束后并不会自动退出,因为线程池中的线程在执行完任务后并不死亡,而是等待执行新的任务,如果希望在程序在执行完所有任务后退出,需要调用ExecutorService接口中的shutdown方法来关闭线程池

void shutdown()
关闭线程池,不再接受新任务,旧任务结束则关闭线程池中所有的线程(等待所有任务,包括等待队列的任务都完成了才关闭线程池)

List<Runnable> shutdownNow()
无论所有任务是否执行结束,立即关闭线程池,List中为等待执行的任务

public class Main{
	
	public static void main(String[] args){
         MyTask task1 = new MyTask("task1", 50);
         MyTask task2 = new MyTask("task2", 50);
         MyTask task3 = new MyTask("task3", 30);
         //创建固定大小的线程池
         ExecutorService threadPool = Executors.newFixedThreadPool(2);
         threadPool.execute(task1);
         threadPool.execute(task2);
         threadPool.execute(task3);
         //所有任务都结束后关闭线程池
         threadPool.shutdown();
	}
}

class MyTask implements Runnable{
	private int count;
	private String taskName;
	public MyTask(String taskName, int count){
		this.count = count;
		this.taskName = taskName;
	}
	public void run(){
		System.out.println("\n"+Thread.currentThread().getName()+"开始执行任务"+taskName+">>");
		for(int i=0;i<count;i++){
			System.out.print(taskName+"-"+i+" ");
		}
		System.out.println("\n"+taskName+"任务执行结束。。");
	}
}

运行结果:

pool-1-thread-1开始执行任务task1>>

pool-1-thread-2开始执行任务task2>>
task1-0 task2-0 task1-1 task2-1 task1-2 task2-2 task1-3 task2-3 task1-4 task2-4 task1-5 task2-5 task1-6 task2-6 task1-7 task2-7 task1-8 task2-8 task1-9 task2-9 task1-10 task1-11 task1-12 task1-13 task2-10 task1-14 task2-11 task1-15 task2-12 task1-16 task2-13 task1-17 task2-14 task1-18 task2-15 task1-19 task2-16 task1-20 task2-17 task1-21 task2-18 task1-22 task2-19 task1-23 task2-20 task1-24 task2-21 task1-25 task2-22 task2-23 task2-24 task2-25 task2-26 task2-27 task1-26 task2-28 task2-29 task2-30 task1-27 task2-31 task2-32 task1-28 task2-33 task2-34 task2-35 task2-36 task2-37 task2-38 task2-39 task2-40 task2-41 task2-42 task2-43 task2-44 task2-45 task2-46 task2-47 task2-48 task2-49 
task2任务执行结束。。
task1-29 task1-30 
pool-1-thread-2开始执行任务task3>>
task3-0 task3-1 task3-2 task3-3 task3-4 task3-5 task3-6 task3-7 task3-8 task3-9 task3-10 task3-11 task3-12 task3-13 task3-14 task3-15 task3-16 task3-17 task3-18 task3-19 task3-20 task3-21 task3-22 task3-23 task3-24 task3-25 task1-31 task3-26 task3-27 task3-28 task3-29 
task3任务执行结束。。
task1-32 task1-33 task1-34 task1-35 task1-36 task1-37 task1-38 task1-39 task1-40 task1-41 task1-42 task1-43 task1-44 task1-45 task1-46 task1-47 task1-48 task1-49 
task1任务执行结束。。

从结果中可以看出,线程池中的两个线程pool-1-thread-1、pool-1-thread-2分别执行了task1、task2,
pool-1-thread-2执行完task2后接着又执行了task3

实际开发中,线程池一般只有一个,用其中的线程完成各种任务。
如果需要执行的任务数量大于线程池的尺寸,则有的任务要进入此线程池的的等待队列

单任务线程池的使用

同一时刻只允许执行一个任务,而且要求任务按照请求的顺序执行

public class Main{
	
	public static void main(String[] args){
         MyTask task1 = new MyTask("task1", 20);
         MyTask task2 = new MyTask("task2", 20);
         MyTask task3 = new MyTask("task3", 10);
         //创建单任务线程池
         ExecutorService singlePool = Executors.newSingleThreadExecutor();
         singlePool.execute(task1);
         singlePool.execute(task2);
         singlePool.execute(task3);
         //所有任务都结束后关闭线程池
         singlePool.shutdown();
	}
}

class MyTask implements Runnable{
	private int count;
	private String taskName;
	public MyTask(String taskName, int count){
		this.count = count;
		this.taskName = taskName;
	}
	public void run(){
		System.out.println("\n"+Thread.currentThread().getName()+"开始执行任务"+taskName+">>");
		for(int i=0;i<count;i++){
			System.out.print(taskName+"-"+i+" ");
		}
		System.out.println("\n"+taskName+"任务执行结束。。");
	}
}

运行结构:

pool-1-thread-1开始执行任务task1>>
task1-0 task1-1 task1-2 task1-3 task1-4 task1-5 task1-6 task1-7 task1-8 task1-9 task1-10 task1-11 task1-12 task1-13 task1-14 task1-15 task1-16 task1-17 task1-18 task1-19 
task1任务执行结束。。

pool-1-thread-1开始执行任务task2>>
task2-0 task2-1 task2-2 task2-3 task2-4 task2-5 task2-6 task2-7 task2-8 task2-9 task2-10 task2-11 task2-12 task2-13 task2-14 task2-15 task2-16 task2-17 task2-18 task2-19 
task2任务执行结束。。

pool-1-thread-1开始执行任务task3>>
task3-0 task3-1 task3-2 task3-3 task3-4 task3-5 task3-6 task3-7 task3-8 task3-9 
task3任务执行结束。。

创建大小可变的线程池

public static ExecutorService newCachedThreadPool()

创建一个大小可变的线程池,当执行任务时先选取重用缓存已有的空闲线程来完成任务,如果没有空闲线程,则创建新线程
空闲超过60秒的线程将被从线程池中删除

...

public static void main(String[] args){
         MyTask task1 = new MyTask("task1", 30);
         MyTask task2 = new MyTask("task2", 30);
         MyTask task3 = new MyTask("task3", 20);
         //创建大小可变的线程池
         ExecutorService threadPool = Executors.newCachedThreadPool();
         threadPool.execute(task1);
         threadPool.execute(task2);
         threadPool.execute(task3);
         //所有任务都结束后关闭线程池
         threadPool.shutdown();
	}
	
...

运行结果:

pool-1-thread-1开始执行任务task1 >>
task1-0 task1-1 task1-2 
pool-1-thread-2开始执行任务task2 >>
task1-3 task1-4 task1-5 task1-6 
pool-1-thread-3开始执行任务task3 >>
task3-0 task3-1 task3-2 task3-3 task3-4 task3-5 task3-6 task1-7 task3-7 task3-8 task3-9 task2-0 task3-10 task1-8 task3-11 task3-12 task3-13 task3-14 task3-15 task3-16 task3-17 task3-18 task2-1 task3-19 task1-9 
task3任务执行结束 。。
task2-2 task2-3 task2-4 task2-5 task2-6 task2-7 task2-8 task2-9 task2-10 task2-11 task2-12 task2-13 task2-14 task2-15 task1-10 task2-16 task1-11 task2-17 task2-18 task2-19 task1-12 task2-20 task2-21 task1-13 task2-22 task1-14 task2-23 task1-15 task2-24 task1-16 task1-17 task1-18 task1-19 task1-20 task1-21 task1-22 task1-23 task2-25 task1-24 task2-26 task1-25 task2-27 task1-26 task2-28 task1-27 task2-29 task1-28 
task2任务执行结束 。。
task1-29 
task1任务执行结束 。。

三个任务交替执行,可变尺寸的线程池可以根据任务的多少来自动调整待命线程的数量,优化执行性能。

延迟线程池

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

corePoolSize,线程池中线程的数量

public static ScheduledExecutorService newSingleThreadScheduledExecutor()

创建一个延迟线程池,其中只有一个待命线程

以上两个方法返回的都是ScheduledExecutorService,是ExecutorService的子接口,特有的方法schedule来延迟执行指定的任务

ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
//TimeUnit为枚举类型
...

	public static void main(String[] args){
         MyTask task1 = new MyTask("task1", 30);
         MyTask task2 = new MyTask("task2", 30);
         MyTask task3 = new MyTask("task3", 20);
         //创建有时延的线程池
         ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
         //创建单线程延时线程池
         ScheduledExecutorService singleThreadPool = Executors.newSingleThreadScheduledExecutor();
         
         threadPool.schedule(task1, 1, TimeUnit.SECONDS);
         threadPool.schedule(task2, 1500, TimeUnit.MILLISECONDS);
         singleThreadPool.schedule(task3, 2000, TimeUnit.MILLISECONDS);
         
         //所有任务都结束后关闭线程池
         threadPool.shutdown();
         singleThreadPool.shutdown();
	}
	
...

运行结果:

pool-1-thread-1开始执行任务task1 >>
task1-0 task1-1 task1-2 task1-3 task1-4 task1-5 task1-6 task1-7 task1-8 task1-9 task1-10 task1-11 task1-12 task1-13 task1-14 task1-15 task1-16 task1-17 task1-18 task1-19 task1-20 task1-21 task1-22 task1-23 task1-24 task1-25 task1-26 task1-27 task1-28 task1-29 
task1任务执行结束 。。

pool-1-thread-2开始执行任务task2 >>
task2-0 task2-1 task2-2 task2-3 task2-4 task2-5 task2-6 task2-7 task2-8 task2-9 task2-10 task2-11 task2-12 task2-13 task2-14 task2-15 task2-16 task2-17 task2-18 task2-19 task2-20 task2-21 task2-22 task2-23 task2-24 task2-25 task2-26 task2-27 task2-28 task2-29 
task2任务执行结束 。。

pool-2-thread-1开始执行任务task3 >>
task3-0 task3-1 task3-2 task3-3 task3-4 task3-5 task3-6 task3-7 task3-8 task3-9 task3-10 task3-11 task3-12 task3-13 task3-14 task3-15 task3-16 task3-17 task3-18 task3-19 
task3任务执行结束 。。

自定义参数的线程池

使用ThreadPoolExecutor类(实现了ExecutorService)来实现自定义的线程池,当有新任务到达时,按照以下规则处理:
1)如果当前线程池中的线程数量比规定标准值少,则倾向于创建线程;
2)如果当前线程池中的线程数量比规定标准值多,则倾向于把新的任务放到队列中;如果队列已满,并且线程数量没有超过最大值,则创建新线程。
3)如果当前线程池中的线程数量已达最大值,且队列已满,则请求被拒绝。
4)如果空闲线程超过预设的存活时间,则将空闲线程对象销毁。

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)

ThreadPoolExecutor类一些常用的方法:
public int getCorePoolSize() 获取线程池的标准大小
public int getActiveCount() 返回线程池中正在执行任务的线程数量
public int getPoolSize() 获取线程池的当前大小
public int getMaximumPoolSize() 获取线程池的最大大小
public BlockingQueue<Runnable> getQueue() 返回线程池的工作等待队列

...

public static void main(String[] args){
         MyTask task1 = new MyTask("task1", 30);
         MyTask task2 = new MyTask("task2", 30);
         MyTask task3 = new MyTask("task3", 20);
         MyTask task4 = new MyTask("task4", 20);
         //创建工作等待队列
         BlockingQueue workQueue = new ArrayBlockingQueue(3);
         //创建自定义线程池
         ThreadPoolExecutor myThreadPool = new ThreadPoolExecutor(
        		 2, 4, 100, TimeUnit.SECONDS, workQueue);
         myThreadPool.execute(task1);
         myThreadPool.execute(task2);
         myThreadPool.execute(task3);
         myThreadPool.execute(task4);
         //所有任务都结束后关闭线程池
         myThreadPool.shutdown();
	}

...

运行结果:

pool-1-thread-1开始执行任务task1 >>
task1-0 task1-1 task1-2 task1-3 task1-4 
pool-1-thread-2开始执行任务task2 >>
线程池的当前线程数:2
task2-0 task2-1 task2-2 task2-3 task2-4 task2-5 task2-6 task2-7 task2-8 task2-9 task2-10 task2-11 task2-12 task2-13 task2-14 task2-15 task2-16 task2-17 task2-18 task2-19 task2-20 task1-5 task2-21 task1-6 task2-22 task1-7 task2-23 task1-8 task2-24 task1-9 task2-25 task1-10 task2-26 task1-11 task2-27 task1-12 task2-28 task2-29 task1-13 
task2任务执行结束 。。
task1-14 task1-15 
pool-1-thread-2开始执行任务task3 >>
task1-16 task3-0 task1-17 task3-1 task3-2 task3-3 task1-18 task3-4 task1-19 task3-5 task1-20 task3-6 task1-21 task3-7 task1-22 task3-8 task1-23 task3-9 task1-24 task3-10 task1-25 task3-11 task1-26 task3-12 task1-27 task3-13 task1-28 task3-14 task1-29 task3-15 
task1任务执行结束 。。
task3-16 
pool-1-thread-1开始执行任务task4 >>
task3-17 task4-0 task3-18 task4-1 task3-19 task4-2 
task3任务执行结束 。。
task4-3 task4-4 task4-5 task4-6 task4-7 task4-8 task4-9 task4-10 task4-11 task4-12 task4-13 task4-14 task4-15 task4-16 task4-17 task4-18 task4-19 
task4任务执行结束 。。
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值