多线程软件设计方法可以最大限度地发挥现代多核处理器的计算能力,提高生产系统的吞吐量和性能;
JDK提供的Execotur框架:
1、固定大小线程池newFixedThreadPool
5个固定大小的线程池,提交10个任务,分2批执行任务;
public class ThreadPoolDemo {
public static class MyTask implements Runnable {
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println(System.currentTimeMillis() + ":" + this.name + ":" + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(5);
// ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
exec.submit(new MyTask("task" + i));
}
exec.shutdown();
}
}
console
1550367982546:task1:pool-1-thread-2
1550367982546:task2:pool-1-thread-3
1550367982546:task0:pool-1-thread-1
1550367982547:task3:pool-1-thread-4
1550367982547:task4:pool-1-thread-5
1550367983551:task5:pool-1-thread-5
1550367983551:task6:pool-1-thread-1
1550367983552:task7:pool-1-thread-4
1550367983552:task9:pool-1-thread-3
1550367983552:task8:pool-1-thread-2
2、newCachedThreadPool
如果换成Executors.newCachedThreadPool();则直接创建10个线程执行任务,打印如下:
1550369486518:task1:pool-1-thread-2
1550369486518:task0:pool-1-thread-1
1550369486518:task2:pool-1-thread-3
1550369486519:task3:pool-1-thread-4
1550369486519:task4:pool-1-thread-5
1550369486519:task5:pool-1-thread-6
1550369486519:task6:pool-1-thread-7
1550369486520:task7:pool-1-thread-8
1550369486520:task8:pool-1-thread-9
1550369486520:task9:pool-1-thread-10
3、计划任务 ScheduledExecutorService
3.1 scheduleAtFixedRate
任务调度的频率是一定的
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 3, TimeUnit.SECONDS);
}
}
任务执行需要先1秒多,任务间隔是3秒,所以打印如下:
1550384755251
1550384758254
1550384761254
如果将任务执行需要1秒改为5秒,即任务执行所需时间5秒大于任务执行间隔,则任务执行完之后立即执行下一个任务,即任务间隔改为5秒;
1550384873823
1550384878828
1550384883834
3.2 scheduleWithFixedDelay
任务之间的间隔是一定的
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);
ses.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 3, TimeUnit.SECONDS);
}
}
任务1秒,间隔3秒,打印出来间隔为4秒:
1550385980234
1550385984244
1550385988253
1550385992261
1550385996265
如果将任务执行需要1秒改为5秒,则打印出来实际间隔为8秒:
1550386073645
1550386081648
1550386089651
1550386097654
1550386105664
4、调度程序不一定会无限期地持续执行,如果任务本身抛出异常,后续的所有执行都会中断!
必须做好异常处理!