预览加载中,请您耐心等待几秒...
1/8
2/8
3/8
4/8
5/8
6/8
7/8
8/8

在线预览结束,喜欢就下载吧,查找使用更方便

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

Java多线程开发技巧Java多线程开发技巧很多开发者谈到Java多线程开发,仅仅停留在newThread(...).start()或直接使用Executor框架这个层面,对于线程的管理和控制却不够深入,通过读Java并发编程实践了解到了很多不为我知但又非常重要的细节,今日整理如下。不应用线程池的缺点有些开发者图省事,遇到需要多线程处理的地方,直接newThread(...).start(),对于一般场景是没问题的,但如果是在并发请求很高的情况下,就会有些隐患:新建线程的开销。线程虽然比进程要轻量许多,但对于JVM来说,新建一个线程的代价还是挺大的,决不同于新建一个对象资源消耗量。没有一个池来限制线程的数量,会导致线程的数量直接取决于应用的并发量,这样有潜在的线程数据巨大的可能,那么资源消耗量将是巨大的稳定性。当线程数量超过系统资源所能承受的程度,稳定性就会成问题制定执行策略在每个需要多线程处理的地方,不管并发量有多大,需要考虑线程的执行策略任务以什么顺序执行可以有多少个任何并发执行可以有多少个任务进入等待执行队列系统过载的时候,应该放弃哪些任务?如何通知到应用程序?一个任务的执行前后应该做什么处理线程池的类型不管是通过Executors创建线程池,还是通过Spring来管理,都得清楚知道有哪几种线程池:FixedThreadPool:定长线程池,提交任务时创建线程,直到池的最大容量,如果有线程非预期结束,会补充新线程CachedThreadPool:可变线程池,它犹如一个弹簧,如果没有任务需求时,它回收空闲线程,如果需求增加,则按需增加线程,不对池的大小做限制SingleThreadExecutor:单线程。处理不过来的任务会进入FIFO队列等待执行SecheduledThreadPool:周期性线程池。支持执行周期性线程任务其实,这些不同类型的线程池都是通过构建一个ThreadPoolExecutor来完成的,所不同的是corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory这么几个参数。具体可以参见JDKDOC。线程池饱和策略由以上线程池类型可知,除了CachedThreadPool其他线程池都有饱和的可能,当饱和以后就需要相应的策略处理请求线程的任务,ThreadPoolExecutor采取的方式通过队列来存储这些任务,当然会根据池类型不同选择不同的队列,比如FixedThreadPool和SingleThreadExecutor默认采用的是无限长度的LinkedBlockingQueue。但从系统可控性讲,最好的做法是使用定长的ArrayBlockingQueue或有限的LinkedBlockingQueue,并且当达到上限时通过ThreadPoolExecutor.setRejectedExecutionHandler方法设置一个拒绝任务的策略,JDK提供了AbortPolicy、CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy几种策略,具体差异可见JDKDOC线程无依赖性线程之间的依赖性。如果线程有依赖可能会造成死锁或饥饿调用者与线程的依赖性。调用者得监视线程的完成情况,影响可并发量当然,在有些业务里确实需要一定的依赖性,比如调用者需要得到线程完成后结果,传统的Thread是不便完成的,因为run方法无返回值,只能通过一些共享的变量来传递结果,但在Executor框架里可以通过Future和Callable实现需要有返回值的任务,当然线程的异步性导致需要有相应机制来保证调用者能等待任务完成,关于Future和Callable的用法见下面的实例就一目了然了:publicclassFutureRenderer{privatefinalExecutorServiceexecutor=...;voidrenderPage(CharSequencesource){finalList<ImageInfo>imageInfos=scanForImageInfo(source);Callable<List<ImageData>>task=newCallable<List<ImageData>>(){publicList<ImageData>call(){List<ImageData>result=newArrayList<ImageData>();for(ImageInfoimageInfo:imageInfos)result.add(imageInfo.downloadImage());returnresult;}};Future<List<ImageData>>future=executo