博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android--从线程到线程池
阅读量:2232 次
发布时间:2019-05-09

本文共 6386 字,大约阅读时间需要 21 分钟。

在了解线程池之前,首先我们先了解什么是线程

在JAVA中,有两种方式创建线程

1、实现Runnable接口,实例化Thread;2 、继承Thread类,重写run()方法

区别:

Thread需要实现Runnable ,Runnable没有start()方法,只有Thread类中才有

(该段摘自百度)

http://wenku.baidu.com/link?url=Nxc165sfKCfnRuCnkZnNGNfF5ReG0tHU5cuYf-nrwhXnt-dX7ANAri-sjFUR_XfENJd-zBzKqIUvy5axb6V--vv8akTUV6AffaqGR5Xg1BC

在实际开发中一个多线程的操作很少使用Thread类,而是通过Runnable接口完成。 

1、避免点继承的局限,一个类可以继承多个接口。2、适合于资源的共享

以常见的卖票为例

A: 通过Thread 类完成:

首先,定义一个窗口用于卖票的线程

public class MyThread extends Thread{	private int count =10;	private String name ;	public MyThread(String name){		this.name = name;	}	@Override	public void run() {		// TODO Auto-generated method stub			for(int i = 0;i<20;i++){				//i 表示该窗口卖出的张数对应的人的位数				if(this.count>0){					System.out.println(this.name+"買到第:"+count--+"張票");				}			}	}}
接着,创建三个线程,同时卖票,我们看看会有什么样的结果,代码如下

public class TicketThread {	public static void main(String[] args) {		MyThread m1 = new MyThread("one");		MyThread m2 = new MyThread("two");		MyThread m3 = new MyThread("three");		m1.start();		m2.start();		m3.start();			}}
三个线程开启后,控制台输出的结果如下:

two買到第:10張票three買到第:10張票one買到第:10張票three買到第:9張票two買到第:9張票three買到第:8張票one買到第:9張票three買到第:7張票two買到第:8張票three買到第:6張票one買到第:8張票one買到第:7張票three買到第:5張票two買到第:7張票three買到第:4張票one買到第:6張票three買到第:3張票two買到第:6張票three買到第:2張票one買到第:5張票three買到第:1張票two買到第:5張票one買到第:4張票two買到第:4張票one買到第:3張票two買到第:3張票one買到第:2張票two買到第:2張票one買到第:1張票two買到第:1張票
很明显,三个线程都默认10张票归自己所有,当三个线程开启后,一个卖出了30张票,线程与线程之间并没有进行数据的交互

现在我们实现第二种方案:实现Runnable 接口

同样的,让我们的MyThread 实现Runnable 接口

public class MyThread implements Runnable{private int count = 10;	@Override	public void run() {		// TODO Auto-generated method stub		for(int i = 10;i<20;i++){			synchronized (this)//同步			{				if(this.count>0){					System.out.println("買到第:"+count--+"張票");									}			}					}	}	}
相对应的操作类

public class TicketThread {	public static void main(String[] args) {		MyThread thread = new MyThread();		new Thread(thread).start();		new Thread(thread).start();		new Thread(thread).start();	}}
再来看一下输出的结果:

買到第:10張票買到第:9張票買到第:8張票買到第:7張票買到第:6張票買到第:5張票買到第:4張票買到第:3張票買到第:2張票買到第:1張票
---------------------------------------------------------------华丽的分割线----------------------------------------------------------------------

现在了解了Java中的线程,现在我们就进一步了解更难的知识

线程池

同样的,我们先了解一下什么是线程池

为什么要使用线程池:

1、开发者可以重复使用线程池中的线程,避免不必要的创建与销毁;

2、可以对线程进行一些简单的操作,例如时间的控制等;

3、控制线程的数量,避免大量线程并发时造成内存的损耗

一个线程执行任务所需要的时间为:创建时间+执行任务时间+销毁时间

若滥用线程,则容易导致不必要的浪费。线程池的使用正是减少了创建和销毁线程的时间,从而达到节省开销的目的。

现在,我们就来了解下线程池

线程池的构造方法:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,                          TimeUnit unit, BlockingQueue
workQueue)
用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的
ThreadPoolExecutor。使用 工厂方法之一比使用此通用构造方法方便得多。
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由
execute 方法提交的
Runnable 任务。
抛出:
- 如果 corePoolSize 或 keepAliveTime 小于 0,或者 maximumPoolSize 小于等于 0,或者 corePoolSize 大于 maximumPoolSize。
- 如果
workQueue 为 null
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, ThreadFactory threadFactory) 用给定的初始参数和默认被拒绝的执行处理程序创建新的 ThreadPoolExecutor。
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由
execute 方法提交的
Runnable 任务。
threadFactory - 执行程序创建新线程时使用的工厂。
抛出:
- 如果 corePoolSize 或 keepAliveTime 小于 0,或者 maximumPoolSize 小于等于 0,或者 corePoolSize 大于 maximumPoolSize。
- 如果
workQueue 或
threadFactory 为 null。
 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, RejectedExecutionHandler handler)
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅由保持
execute 方法提交的
Runnable 任务。
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
抛出:
- 如果 corePoolSize 或 keepAliveTime 小于 0,或者 maximumPoolSize 小于等于 0,或者 corePoolSize 大于 maximumPoolSize。
- 如果
workQueue 或
handler 为 null。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue
workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由
execute 方法提交的
Runnable 任务。
threadFactory - 执行程序创建新线程时使用的工厂。
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
抛出:
- 如果 corePoolSize 或 keepAliveTime 小于 0,或者 maximumPoolSize 小于等于 0,或者 corePoolSize 大于 maximumPoolSize。
- 如果
workQueue、
threadFactory 或
handler 为 null。
这里提一下RejectedExecutionHandler

这是程池对拒绝任务的处理策略。一般是队列已满或者无法成功执行任务,这时ThreadPoolExecutor会调用handler的rejectedExecution方法来通知调用者

默认有四个拒绝策略

1、ThreadPoolExecutor.AbortPolicy()   直接抛出异常RejectedExecutionException  2、ThreadPoolExecutor.CallerRunsPolicy()    直接调用run方法并且阻塞执行  3、ThreadPoolExecutor.DiscardPolicy()   直接丢弃后来的任务  4、ThreadPoolExecutor.DiscardOldestPolicy()  丢弃在队列中队首的任务

官方定义的四种线程池

1、FixedThreadPool
线程池中的线程数量固定,并且任务队列的大小没有限制,并且在线程池中只有核心线程,故如果线程处于空闲状态也不会被回收
正因为其不会被回收,所以响应是最快的
2、CachedThreadPool
缓存线程池,线程池中没有核心线程,如果有空闲线程时,会利用其进行处理任务,所以任何添加进来的任务都会立刻执行,但前提是在缺省时间(60s)内,超过时长线程将会被移除线程池,该线程池适合大量的用时较少的异步任务;
3、ScheduledThreadPool
线程池中核心线程数固定,非核心线程数不固定,所以非核心线程空闲时会被收回;
4、SingleThreadExecutor
顾名思义,单线程池,线程池中只有一个核心线程,所有任务在同一线程中进行

转载地址:http://wsbbb.baihongyu.com/

你可能感兴趣的文章
hibernate延迟加载(get和load的区别)
查看>>
关于文件拷贝效率问题
查看>>
MyBatis分页插件PageHelper的使用
查看>>
【MyBatis学习01】宏观上把握MyBatis框架
查看>>
【MyBatis学习02】走进MyBatis的世界
查看>>
【MyBatis学习03】原始dao开发方法及其弊端
查看>>
【MyBatis学习04】mapper代理方法开发dao
查看>>
【MyBatis学习05】SqlMapConfig.xml文件中的配置总结
查看>>
【MyBatis学习06】输入映射和输出映射
查看>>
【MyBatis学习07】动态sql
查看>>
【MyBatis学习08】高级映射之一对一查询
查看>>
【MyBatis学习09】高级映射之一对多查询
查看>>
【MyBatis学习10】高级映射之多对多查询
查看>>
【MyBatis学习11】MyBatis中的延迟加载
查看>>
【MyBatis学习12】MyBatis中的一级缓存
查看>>
【MyBatis学习13】MyBatis中的二级缓存
查看>>
【MyBatis学习14】MyBatis和Spring整合
查看>>
【MyBatis学习15】MyBatis的逆向工程生成代码
查看>>
Java 中 final、finally 和 finalize 使用总结
查看>>
volatile关键字解析
查看>>