1.new Thread的弊端
执行一个异步任务你还只是如下new Thread吗?
new Thread( new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
}).start();
1-1 说说弊端:
a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。
1-2 相比new Thread,Java提供的四种线程池的好处在于:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。
2.Executors提供四种线程池
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程池的规模不存在限制。
newFixedThreadPool 创建一个固定长度线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个固定长度线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
将线程放入线程池的两种方法
1- ExecutorService 类中的 submit(Runnable
submit(Callable<T> task)
2- Executor 接口中的execute(Runnable
3.实例
3-1 newCachedThreadPool
package com.th.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by Administrator on 2018/6/6.
* newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,
* 若无可回收,则新建线程。线程池的规模不存在限制。
*/
public class NewCachedThreadPool {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//1- 在未来某个时间执行给定的命令。
// 该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
//2- 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
// 该 Future 的 get 方法在成功完成时将会返回给定的结果
cachedThreadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
}
cachedThreadPool.shutdown();
}
}
3-2 newFixedThreadPool
package com.th.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by Administrator on 2018/6/6.
*
* newFixedThreadPool 创建一个固定长度线程池,可控制线程最大并发数,超出的线程会在队列中等待。
*/
public class NewFixedThreadPool {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; i++)
{
final int index = i;
//1- 在未来某个时间执行给定的命令。
// 该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
threadRunMethod(index);
}
});
//2- 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
// 该 Future 的 get 方法在成功完成时将会返回给定的结果
fixedThreadPool.submit(new Runnable() {
@Override
public void run() {
threadRunMethod(index);
}
});
}
fixedThreadPool.shutdown();
}
/**
*
* @param index
*/
private static void threadRunMethod(int index) {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3-3 newScheduledThreadPool
package com.th.threadPool;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by Administrator on 2018/6/6.
* newScheduledThreadPool 创建一个固定长度线程池,支持定时及周期性任务执行。
*/
public class NewScheduledThreadPool {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
//testSchedule(scheduledExecutorService);
//testScheduleAtFixedRate(scheduledExecutorService);
testScheduleWithFixedDelay(scheduledExecutorService);
// 终止线程池
//scheduledExecutorService.shutdown();
}
/**
*
* 跟 testScheduleAtFixedRate 非常类似,就是延迟的时间有点区别
* 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
* 也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,
* 接着在 initialDelay + 2 * period 后执行,依此类推。
*
* 如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
* 推迟的时间 : 等到上次的任务执行完之后再延迟period 的时间后执行。
* @param scheduledExecutorService
*/
private static void testScheduleWithFixedDelay(ScheduledExecutorService scheduledExecutorService) {
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
System.out.println("延迟2秒,再3秒执行一次");
//如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
//本次任务执行完后下次的任务还需要延迟period时间后再执行
Thread.sleep(6*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},2,3,TimeUnit.SECONDS);
}
/**
* 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
* 也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,
* 接着在 initialDelay + 2 * period 后执行,依此类推。
*
* 如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
* 推迟的时间 : 等到上次的任务执行完就立马执行。
* @param scheduledExecutorService
*/
private static void testScheduleAtFixedRate(ScheduledExecutorService scheduledExecutorService) {
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
System.out.println("延迟2秒,再3秒执行一次");
//如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
//如果任务里面执行的时间大于 period 的时间,本次任务执行完后,下次任务立马执行。
Thread.sleep(6*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},2,3,TimeUnit.SECONDS);
}
/**
* 创建并执行在给定延迟后启用的一次性操作
* @param scheduledExecutorService
*/
private static void testSchedule(ScheduledExecutorService scheduledExecutorService) {
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
}
}
3-4 newSingleThreadExecutor
package com.th.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by Administrator on 2018/6/6.
* newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,
* 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
*/
public class NewSingleThreadExecutor {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
/*singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("newSingleThreadExecutor: " + index);
Thread.sleep(2*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
});*/
singleThreadExecutor.submit(new Runnable() {
@Override
public void run() {
try {
System.out.println("newSingleThreadExecutor: " + index);
Thread.sleep(2*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
singleThreadExecutor.shutdown();
}
}