当需求场景为处理大量并发任务时,我们通常使用线程池来优化性能。Java线程池可以控制并发线程数量,避免资源超额占用以及线程切换开销过大的问题。常见的线程池类有ThreadPoolExecutor和Executors等。在使用线程池时,我们可以通过不同的线程池参数及处理方式控制任务执行效率。
一、Java线程池的创建
//创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
ThreadPoolExecutor类可以通过自定义的方式创建线程池,通过以下参数控制线程池:
- corePoolSize:核心线程数,当提交任务数小于核心线程数时,即使有其他空闲线程也不会创建,只有当核心线程都已经处于忙碌状态时,才会创建新的线程执行。
- maximumPoolSize:最大线程数,线程池中最大线程数不能超过该参数。当提交任务数超过核心线程数时,会不断创建新的线程,直到线程数达到最大值。
- keepAliveTime:线程池中空闲线程的存活时间。
- unit:keepAliveTime的时间单位。
- workQueue:任务队列,用于存储待执行的任务。
二、Java线程池的执行方式
线程池通过execute方法执行线程任务,该方法可以接收Runnable和Callable两种类型的参数。
- Runnable
Runnable是一个接口,实现该接口后,需要重写run方法,将要执行的任务放在该方法里。
示例1:
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " -> start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " -> end");
}
});
示例2:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " -> start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " -> end");
}
}
MyRunnable myRunnable = new MyRunnable();
threadPool.execute(myRunnable);
上面两个示例都是通过execute方法提交Runnable任务,实现了多个任务并发执行的效果。
- Callable
Callable也是一个接口,实现该接口后,需要重写call方法,该方法可以返回一个结果对象。
示例3:
Future<String> future = threadPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + " -> start");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + " -> end");
return "hello, callable!";
}
});
try {
//等待任务执行完成并获取执行结果
String result = future.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
上面示例3是通过submit方法提交Callable任务到线程池中并返回Future对象,可以通过该对象获取正在执行的状态和执行结果。
三、Java线程池的关闭与退出
当不再需要线程池时,需要将其关闭,以避免线程池一直处于运行状态、占用资源。线程池的关闭有两种方式:
- shutdown()
该方法要求线程池中的任务执行完后退出。该方法会等待当前正在执行的任务执行完或者等待超时,如果超时则进行强制关闭。
threadPool.shutdown();
- shutdownNow()
该方法会立即强制关闭线程池,不管任务是否结束。如果正在执行的任务被中断,则任务将返回一个InterruptedException。
threadPool.shutdownNow();
四、Java线程池的异常处理
当线程池中发生异常时,需要对其进行处理。可以通过自定义ThreadFactory的方式创建线程池,对异常进行捕获和处理。
public class CustomThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程" + t.getName() + "发生了异常:" + e.getMessage());
}
});
return thread;
}
}
ExecutorService threadPool = new ThreadPoolExecutor(
5, 10, 10,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(50),
new CustomThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
在上面的示例中,通过自定义ThreadFactory并设置UncaughtExceptionHandler对异常进行捕获和处理,当线程池中的线程发生异常时,会打印出异常信息。
以上就是Java线程池并发执行多个任务的完整攻略,通过示例讲解了如何创建线程池、不同任务执行方式以及线程池的关闭、异常处理等重要内容,可以对Java线程池相关知识进行全面学习。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java线程池并发执行多个任务方式 - Python技术站