- 认识cpu、核心与线程
- java多线程系列(一)之java多线程技能
- java多线程系列(二)之对象变量的并发访问
- java多线程系列(三)之等待通知机制
- java多线程系列(四)之ReentrantLock的使用
- java多线程系列(五)之synchronized ReentrantLock volatile Atomic 原理分析
- java多线程系列(六)之线程池原理及其使用
ExecutorService——newScheduledThreadPool使用功能测试
测试目的
学习ScheduledExecutorService类创建的newScheduledThreadPool相关用法
具体事例
创建newScheduledThreadPool及scheduleAtFixedRate和scheduleWithFixedDelay方法的使用。
package com.secbro.test.thread;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
* @author zhuzhisheng
* @Description
* @date on 2016/6/1.
*/
public class TestNewScheduledThreadPool {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
scheduleAtFixedRate(service,1000);
scheduleAtFixedRate(service,6000);
scheduleWithFixedDelay(service,1000);
scheduleWithFixedDelay(service,6000);
}
private static void scheduleAtFixedRate(ScheduledExecutorService service, final int sleepTime){
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
long start = new Date().getTime();
System.out.println("scheduleAtFixedRate 开始执行时间:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = new Date().getTime();
System.out.println("scheduleAtFixedRate 执行花费时间=" + (end -start)/1000 + "m");
System.out.println("scheduleAtFixedRate 执行完成时间:"
+ DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================");
}
},1000,5000,TimeUnit.MILLISECONDS);
}
private static void scheduleWithFixedDelay(ScheduledExecutorService service,final int sleepTime){
service.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
long start = new Date().getTime();
System.out.println("scheduleWithFixedDelay 开始执行时间:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = new Date().getTime();
System.out.println("scheduleWithFixedDelay执行花费时间=" + (end -start)/1000 + "m");
System.out.println("scheduleWithFixedDelay执行完成时间:"
+ DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================");
}
},1000,5000,TimeUnit.MILLISECONDS);
}
}
具体分析
创建一个ScheduledExecutorService线程池的方法,以下为创建一个大小为2的线程池:
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
- 1
scheduleAtFixedRate
实验一
scheduleAtFixedRate(service,1000);
- 1
输出结果为:
scheduleAtFixedRate 开始执行时间:15:03:15
scheduleAtFixedRate 执行花费时间=1m
scheduleAtFixedRate 执行完成时间:15:03:16
======================================
scheduleAtFixedRate 开始执行时间:15:03:20
scheduleAtFixedRate 执行花费时间=1m
scheduleAtFixedRate 执行完成时间:15:03:21
======================================
分析得出:在任务执行时间小于间隔时间的情况下,程序以起始时间为准则,每隔指定时间执行一次,不受任务执行时间影响。
实验二
scheduleAtFixedRate(service,6000);
- 1
输出结果为:
scheduleAtFixedRate 开始执行时间:15:06:12
scheduleAtFixedRate 执行花费时间=6m
scheduleAtFixedRate 执行完成时间:15:06:18
======================================
scheduleAtFixedRate 开始执行时间:15:06:18
scheduleAtFixedRate 执行花费时间=6m
scheduleAtFixedRate 执行完成时间:15:06:24
======================================
scheduleAtFixedRate 开始执行时间:15:06:24
scheduleAtFixedRate 执行花费时间=6m
scheduleAtFixedRate 执行完成时间:15:06:30
分析得出:当执行任务时间大于间隔时间,此方法不会重新开启一个新的任务进行执行,而是等待原有任务执行完成,马上开启下一个任务进行执行。此时,执行间隔时间已经被打乱。
scheduleWithFixedDelay
实验一
scheduleWithFixedDelay(service,1000);
输出结果为:
scheduleWithFixedDelay 开始执行时间:15:11:03
scheduleWithFixedDelay执行花费时间=1m
scheduleWithFixedDelay执行完成时间:15:11:04
======================================
scheduleWithFixedDelay 开始执行时间:15:11:09
scheduleWithFixedDelay执行花费时间=1m
scheduleWithFixedDelay执行完成时间:15:11:10
======================================
分析得出:当执行任务小于延迟时间时,第一个任务执行之后,延迟指定时间,然后开始执行第二个任务。
实验二
scheduleWithFixedDelay(service,6000);
输出结果为:
scheduleWithFixedDelay 开始执行时间:15:12:53
scheduleWithFixedDelay执行花费时间=6m
scheduleWithFixedDelay执行完成时间:15:12:59
======================================
scheduleWithFixedDelay 开始执行时间:15:13:04
scheduleWithFixedDelay执行花费时间=6m
scheduleWithFixedDelay执行完成时间:15:13:10
======================================
得出结论:当执行任务大于延迟时间时,第一个任务执行之后,延迟指定时间,然后开始执行第二个任务。
总之:此方法无论任务执行时间长短,都是当第一个任务执行完成之后,延迟指定时间再开始执行第二个任务
Java 四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
1、继承一个父类的匿名内部类实现:
abstract class People { public abstract void eat(); } public class Demo { public static void main(String[] args) { People p = new People() { public void eat() { System.out.println("I can eat "); } }; p.eat(); } }
2、在接口上使用匿名内部类:
interface People { public void eat(); } public class Demo { public static void main(String[] args) { People p = new People() { public void eat() { System.out.println("I can eat "); } }; p.eat(); } }
此处 new People( )看似实例化了一个接口,事实并非如此,接口式的匿名内部类是实现了一个接口的匿名类。而且只能实现一个接口。
ps再来说一下线程创建的两种方式:
(1)继承Thread类的方式因为耦合性太强,所以一般吧用。
(2)常用实现Runnable接口的创建线程方式。
但是我们更喜欢用匿名内部类的方式来创建一个线程。代码如下:
new Thread(new Runnable() { @Override public void run() { int i=0; while(true){ i++; System.out.println("this is 线程"+i); } } }).start();
就这一句话就可以创建并且启动一个线程,相对来说比较方便。而且特别直观易懂。
此处的new Runnable( )并没有实例化了一个接口