关于executorService
- FixedThreadPool(固定大小)、cachedThreadPool(缓存线程)、SingleThreadExecutor(严格有序的情况使用)
都是ThreadPool的实例,源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
- 在使用fixedThreadPool时关于线程池大小的设定问题:对cpu密集型的任务(如计算1-500w内的素数有多少个)采用N+1,对IO密集型任务(如大量文件读写)采用2N+1。
- 经测试验证,在4核cpu的电脑上线程池大小设置为5与线程池设置为100分别执行100个任务(计算500w内的素数数,每个任务耗时200ms),5个线程的耗时8600ms,100个线程的耗时7600ms,差距不大。
ExecutorService中submit方法与execute的区别,submit接受Callable参数返回future对象,Callable与runnable区别在于Callable中的call方法可有返回值可抛出异常;submit返回的future的对象可以获取任务是否完成,以及任务执行结果(call方法的返回值) ,java启动线程的方式有3种:Thread.start、ExecutorService.execute(runnable)、ExecutorService.submit(callable),前两种都基于runnable
ExecutorService.isTerminate判断所有任务是否完成
关于mysql分区
mysql分区使用关键字PARTITION BY 进行分区,有四种分区方式
RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。
LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。
KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
我这里对一张有着10w数据的表进行了KEY分区,分区字段使用`size`,发现效果显著,同样的查询sql速度快了10倍左右
表字段:id,user_id,mode(1~4),size(2~9)
发现:对mysql进行KEY分区时,分区字段必须是主键(除非该表没有主键或unique约束字段),该表size字段共有8种取值所以我分成了8个区。当查询sql对size进行筛选时,通过explain发现partitions的值只有一个为p1,说明要查的数据在一个分区中就可以找到,如果某个查询的explain的partitions中包含了所有分区说明表分区对这次查询没有起到优化效果,甚至起到反作用,所以进行表分区时,需要根据实际查询情况来选择分区的字段。