目录
5.newSingleThreadScheduledExecutor
Java通过Executors提供四种线程池:
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
- newSingleThreadScheduledExecutor 创建只有一条线程的线程池,他可以在指定延迟后执行线程任务
- newWorkStealingPool(jdk1.8) 更加所需的并行层次来动态创建和关闭线程。会试图减少任务队列的大小,比较适于高负载的环境。比较适用于当执行的任务会创建更多任务,如递归任务。适合使用在很耗时的操作,它是新的线程池类ForkJoinPool的扩展,都是在统一的一个Executors类中实现,由于能够合理的使用CPU进行对任务操作(并行操作),所以适合使用在很耗时的任务中
1.newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
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();
}
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index);
}
});
}
线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
2.newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
// System.out.println(Runtime.getRuntime().availableProcessors());
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
3.newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
表示延迟3秒执行。
定期执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
表示延迟1秒后每3秒执行一次。
4.newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
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(index);
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
结果依次输出,相当于顺序执行各个任务。
5.newSingleThreadScheduledExecutor
创建线程池同时放入多个线程时,每个线程都会按照自己的调度来执行,但是当其中一个线程被阻塞时,其它的线程都会受到影响被阻塞,不过依然都会按照自身调度来执行,但是会存在阻塞延迟。
long start = new Date().getTime();
ScheduledExecutorService excutor = Executors.newSingleThreadScheduledExecutor();
Thread thread1 = new Thread(() -> {
long end = new Date().getTime();
System.out.println("time wait:" + (end - start) + ",this is 线程1");
}, "线程1");
Thread thread2 = new Thread(() -> {
long end = new Date().getTime();
// 测试点,当线程2被阻塞时,其它的线程也被阻塞不能运行
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("time wait:" + (end - start) + ",this is 线程2");
}, "线程2");
Thread thread3 = new Thread(() -> {
long end = new Date().getTime();
System.out.println("time wait:" + (end - start) + ",this is 线程3");
}, "线程3");
excutor.scheduleWithFixedDelay(thread1, 0, 1, TimeUnit.SECONDS);
excutor.scheduleWithFixedDelay(thread2, 0, 2, TimeUnit.SECONDS);
excutor.scheduleWithFixedDelay(thread3, 0, 3, TimeUnit.SECONDS);
6.newWorkStealingPool
newWorkStealingPool适合使用在很耗时的操作,但是newWorkStealingPool不是ThreadPoolExecutor的扩展,它是新的线程池类ForkJoinPool的扩展,但是都是在统一的一个Executors类中实现,由于能够合理的使用CPU进行对任务操作(并行操作),适合使用在很耗时的任务中
// 线程数
final int threads = 10;
// 用于计数线程是否执行完成
CountDownLatch countDownLatch = new CountDownLatch(threads);
int sign = 0;
System.out.println("---- start ----");
ExecutorService executorService = Executors.newWorkStealingPool();
switch (sign) {
case 0:
for (int i = 0; i < threads; i++) {
executorService.execute(() -> {
try {
System.out.println(Thread.currentThread().getName());
} catch (Exception e) {
System.out.println(e);
} finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();
System.out.println("---- end ----");
break;
case 1:
for (int i = 0; i < threads; i++) {
// Callable 带返回值
executorService.submit(new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}));
}
countDownLatch.await();
System.out.println("---- end ----");
break;
case 2:
for (int i = 0; i < threads; i++) {
// Runnable 带返回值
FutureTask<?> futureTask = new FutureTask<>(new Callable<String>() {
@Override
public String call() {
return Thread.currentThread().getName();
}
});
executorService.submit(new Thread(futureTask));
System.out.println(futureTask.get());
}
System.out.println("---- end ----");
break;
}
7.单线程基础
7.1.继承Thread
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
@Test
public void ExtendsThreadTest() {
//创建一个可重用固定线程数的线程池
ExecutorService pool = Executors. newSingleThreadExecutor();
//创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
//关闭线程池
pool.shutdown();
}
7.2.实现Runnable的线程
// 实现了Runnable的线程
public static void RunnableThreadTest() {
ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1);
pool.scheduleAtFixedRate(new Runnable() {// 每隔一段时间就触发异常
@Override
public void run() {
System.out.println("================");
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
pool.scheduleAtFixedRate(new Runnable() {// 每隔一段时间打印系统时间,证明两者是互不影响的
@Override
public void run() {
System.out.println(System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
}
// 测试实现了Runnable的线程
public static void main(String[] args) {
RunnableThreadTest();
}