new Thread()方式
执行一个异步任务,我们可以这样做
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("ThreadName:"+Thread.currentThread().getName());
}
}).start();
以上方式是可以实现的,但是存在诸多弊端:
- 每次都重新 new Thread 新建对象耗费性能;
- 缺乏统一管理,并发情况下可能无休止的创建线程,随时可能 oom;
- 无法灵活执行线程,如定时、公平、中断等;
- 针对耗时较短的异步行为,浪费资源及时间(如下图)
以上我们可以看到,真正的运行状态其实只占整个 Thread 生命周期的一小部分,如果只是为了执行一个耗时或占用资源较小的操作,可能开启线程的消耗比线程工作的周期还要长。
相比 new Thread,Java 提供了四种线程池可用
- Executors.newCachedThreadPool(); //可伸缩线程池
- Executors.newFixedThreadPool(5); //固定数量线程池
- Executors.newSingleThreadExecutor(); //单一线程池
- Executors.newScheduledThreadPool(5); //可定时执行线程池
其实还有一种 single 和 schedule 的结合体 - Executors.newSingleThreadScheduledExecutor();
- newCachedThreadPool
创建一个可伸缩的缓存线程,如果线程池长度超过需要处理的长度,则收回部分线程,如果没有可收回的,就创建新线程,代码如下
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(index * 1000);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
cachedThreadPool.shutdown();
结果如下,当需要执行第 7 个的时候,重复使用了线程 1
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
pool-1-thread-6
pool-1-thread-1
pool-1-thread-7
pool-1-thread-8
pool-1-thread-9
- newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 20; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
fixedThreadPool.shutdown();
因为线程池大小为 4 个,每个任务输出后等待 2 秒,所以每次会打印 4 个线程名字。
定长线程池大小最好是根据业务需求和机器资源配置进行设置,选择一个合适的数字,而不是随意想写多少就写多少。
-
newScheduledThreadPool
创建一个定长线程池,支持定时延期及周期性任务执行。代码如下:
延期 3S 执行ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.schedule(new Runnable() { @Override public void run() { System.out.println("delay 3 seconds"); } }, 3, TimeUnit.SECONDS);
首次延期 1S,然后每 3S 执行一次,倒计时 3 次之后,则退出定时器
CountDownLatch countDownLatch = new CountDownLatch(3); ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("delay 3 seconds"); countDownLatch.countDown(); } }, 1,3, TimeUnit.SECONDS); try { System.out.println("开始等待倒计时..."); countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("倒计时结束"); if (countDownLatch.getCount() == 0L) { scheduledThreadPool.shutdown(); }
-
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { singleThreadExecutor.execute(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName()); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); }
会按照顺序依次执行。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于