Java线程池的四种⽤法与使⽤场景
⽂章⽬录
【转载⾃ : ⼀个程序员的成长 】
【原⽂链接】:
Java线程池的四种⽤法与使⽤场景
⼀、如下⽅式存在的问题
new Thread(){
@Override
public void run(){
// 业务逻辑
}}.start();
1、⾸先频繁的创建、销毁对象是⼀个很消耗性能的事情;
2、如果⽤户量⽐较⼤,导致占⽤过多的资源,可能会导致我们的服务由于资源不⾜⽽宕机;
3、综上所述,在实际的开发中,这种操作其实是不可取的⼀种⽅式。
⼆、使⽤线程池有什么优点
1、线程池中线程的使⽤率提升,减少对象的创建、销毁;
2、线程池可以控制线程数,有效的提升服务器的使⽤资源,避免由于资源不⾜⽽发⽣宕机等问题;
三、线程池的四种使⽤⽅式
1、newCachedThreadPool
创建⼀个线程池,如果线程池中的线程数量过⼤,它可以有效的回收多余的线程,如果线程数不⾜,那么它可以创建新的线程。
public static void method()throws Exception {
ExecutorService executor = wCachedThreadPool();
for(int i =0; i <5; i++){
final int index = i;
Thread.sleep(1000);
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+" "+ index);schedule用法及搭配
}
});
}
}
执⾏结果
通过分析我看可以看到,⾄始⾄终都由⼀个线程执⾏,实现了线程的复⽤,并没有创建多余的线程。
如果当我们的业务需要⼀定的时间进⾏处理,那么将会出现什么结果。我们来模拟⼀下。
可以明显的看出,现在就需要⼏条线程来交替执⾏。
不⾜:这种⽅式虽然可以根据业务场景⾃动的扩展线程数来处理我们的业务,但是最多需要多少个线程同时处理缺是我们⽆法控制的;
优点:如果当第⼆个任务开始,第⼀个任务已经执⾏结束,那么第⼆个任务会复⽤第⼀个任务创建的线程,并不会重新创建新的线程,提⾼了线程的复⽤率;
2、newFixedThreadPool
这种⽅式可以指定线程池中的线程数。举个栗⼦,如果⼀间澡堂⼦最⼤只能容纳20个⼈同时洗澡,那么后⾯来的⼈只能在外⾯排队等待。如果硬往⾥冲,那么只会出现⼀种情景,摩擦摩擦…
⾸先测试⼀下最⼤容量为⼀个线程,那么会不会是我们预测的结果。
public static void method_01()throws InterruptedException {
ExecutorService executor = wFixedThreadPool(1);
for(int i =0; i <10; i++){
Thread.sleep(1000);
final int index = i;
try{
Thread.sleep(2*1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" "+ index);
});
}
executor.shutdown();
}
执⾏结果
我们改为3条线程再来看下结果
优点:两个结果综合说明,newFixedThreadPool的线程数是可以进⾏控制的,因此我们可以通过控制最⼤线程来使我们的服务器打到最⼤的使⽤率,同事⼜可以保证及时流量突然增⼤也不会占⽤服务器过多的资源。
3、newScheduledThreadPool
该线程池⽀持定时,以及周期性的任务执⾏,我们可以延迟任务的执⾏时间,也可以设置⼀个周期性的时间让任务重复执⾏。 该线程池中有以下两种延迟的⽅法。
scheduleAtFixedRate
测试⼀
public static void method_02(){
ScheduledExecutorService executor = wScheduledThreadPool(5);
executor.scheduleAtFixedRate(new Runnable(){
@Override
public void run(){
long start =new Date().getTime();
System.out.println("scheduleAtFixedRate 开始执⾏时间:"+
try{
Thread.sleep(5000);
}catch(InterruptedException e){
e.printStackTrace();
}
long end =new Date().getTime();
System.out.println("scheduleAtFixedRate 执⾏花费时间="+(end - start)/1000+"m");
System.out.println("scheduleAtFixedRate 执⾏完成时间:"+ TimeInstance().format(new Date())) ;
System.out.println("======================================");
}
},1,5, TimeUnit.SECONDS);
}
执⾏结果
测试⼆
总结:以上两种⽅式不同的地⽅是任务的执⾏时间,如果间隔时间⼤于任务的执⾏时间,任务不受执⾏时间的影响。如果间隔时间⼩于任务的执⾏时间,那么任务执⾏结束之后,会⽴马执⾏,⾄此间隔时间就会被打乱。
scheduleWithFixedDelay
测试⼀
public static void method_03(){
ScheduledExecutorService executor = wScheduledThreadPool(2);
executor.scheduleWithFixedDelay(new Runnable(){
@Override
public void run(){
long start =new Date().getTime();
System.out.println("scheduleWithFixedDelay 开始执⾏时间:"+
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
long end =new Date().getTime();
System.out.println("scheduleWithFixedDelay执⾏花费时间="+(end - start)/1000+"m");
System.out.println("scheduleWithFixedDelay执⾏完成时间:"
+ TimeInstance().format(new Date()));
System.out.println("======================================");
}
},1,2, TimeUnit.SECONDS);
}
执⾏结果
测试⼆
public static void method_03(){
ScheduledExecutorService executor = wScheduledThreadPool(2);
executor.scheduleWithFixedDelay(new Runnable(){
@Override
public void run(){
long start =new Date().getTime();
System.out.println("scheduleWithFixedDelay 开始执⾏时间:"+
try{
Thread.sleep(5000);
}catch(InterruptedException e){
e.printStackTrace();
}
long end =new Date().getTime();
System.out.println("scheduleWithFixedDelay执⾏花费时间="+(end - start)/1000+"m");
System.out.println("scheduleWithFixedDelay执⾏完成时间:"
+ TimeInstance().format(new Date()));
System.out.println("======================================");
}
},1,2, TimeUnit.SECONDS);
}
执⾏结果
总结:同样的,跟scheduleWithFixedDelay测试⽅法⼀样,可以测出scheduleWithFixedDelay的间隔时间不会受任务执⾏时间长短的影响。
4、newSingleThreadExecutor
这是⼀个单线程池,⾄始⾄终都由⼀个线程来执⾏。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论