我正在参加「掘金·启航计划」
并发线程的开启
并发可以通过
实现 runable 方法
class TaskTest1 implements Runnable{
@Override
public void run() {
}
}
实现callable方法
class TaskTest implements Callable<String>{
String username;
String password;
@Override
public String call() throws Exception {
return "task";
}
}
继承Thread类
class TaskTest2 extends Thread{
@Override
public void run() {
}
}
实现开启异步的功能
一般使用callable或者实现runable的方法实现使用线程的类
并发线程的执行
不使用Executors的原因
最好不要使用
Executors.newFixedThreadPool
因为newFixedThreadPool的等待队列可以无限长,容易造成oom异常
也不要使用newCachedThreadPool,因为其执行队列可以无限长,容易将资源占满导致oom
ThreadPoolExeutor
ThreadPoolExecutor对象
在介绍Executors创建线程池方法前先介绍一下ThreadPoolExecutor,因为这些创建线程池的静态方法都是返回ThreadPoolExecutor对象,和我们手动创建ThreadPoolExecutor对象的区别就是我们不需要自己传构造函数的参数。ThreadPoolExecutor的构造函数共有四个,但最终调用的都是同一个:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
使用时一般指定五个参数就足够了
new ThreadPoolExecutor(5,
10,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(20));
new ArrayBlockingQueue(20)创建了一个最大对象为20的阻塞队列,大于该队列的请求将被丢弃(或执行拒绝逻辑)
ListenableFuture
ListeningExecutorService是threadPoolExecutor线程池的一个装饰器类,他增加了当任务执行完毕时执行回调函数的功能。
ListenableFuture是Guava库中的一个接口,它扩展了Java标准库中的Future接口,提供了异步执行任务并返回结果的能力。与Java标准库中的Future不同,ListenableFuture可以注册回调函数,在任务完成时自动执行回调函数。
ListenableFuture接口中定义了以下几个方法:
addListener(Runnable listener, Executor executor)方法:注册一个回调函数,在任务完成时执行该回调函数。listener参数是回调函数,executor参数是执行回调函数的Executor对象。isDone()方法:判断任务是否已经完成。get()方法:获取任务的执行结果,如果任务还未完成,则会阻塞当前线程直到任务完成。get(long timeout, TimeUnit unit)方法:获取任务的执行结果,如果任务还未完成,则会阻塞当前线程一段时间,如果在指定的时间内任务仍未完成,则会抛出TimeoutException异常。
ListenableFuture接口的实现类包括SettableFuture和ListeningExecutorService.submit()方法返回的ListenableFutureTask等。
使用ListenableFuture可以方便地实现异步执行任务并在任务完成时执行回调函数的功能,避免了手动创建线程和同步等繁琐的操作。同时,Guava库中的ListenableFuture还提供了一些其他的功能,如转换、合并等,可以进一步简化异步编程的复杂度。
public static void TestThreadPoolExecutor(){
TaskTest taskTest = new TaskTest();
taskTest.username = "123";
taskTest.password = "123";
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
10,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(20));
ListeningExecutorService listeningPool = MoreExecutors.listeningDecorator(threadPoolExecutor);
ListenableFuture<String> submit = listeningPool.submit(taskTest);
//然而这个listen方法并不能有返回值
submit.addListener(new Runnable() {
@Override
public void run() {
System.out.println("方法submit已执行完毕");
}
},threadPoolExecutor);
//addlistener方法添加一个Runable的回调函数,当submit执行完毕之后,会调用第二个参数threadPoolExecutor的线程池执行这个回调函数
}
Future方法
ListeningExecutorService并不能带返回值,无法对线程池内参数传参,可以使用Future类进行管理
public static void TestFuture(){
TaskTest taskTest = new TaskTest();
taskTest.username = "123";
taskTest.password = "123";
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
10,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(20));
ListeningExecutorService listeningPool = MoreExecutors.listeningDecorator(threadPoolExecutor);
ListenableFuture<String> future = listeningPool.submit(taskTest);
/*
FutureCallBack接口可以对每个任务的成功或失败单独做出响应
*/
FutureCallback<String> futureCallback = new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("Futures.addCallback 能带返回值:" + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("出错,业务回滚或补偿");
}
};
//为任务绑定回调接口
Futures.addCallback(future, futureCallback, listeningPool);
}
Futures类的addCallback()方法是Guava库中的一个方法,用于向一个Future对象添加回调函数。回调函数是一种异步编程的技术,它允许在异步计算完成后自动执行一些操作,而无需等待计算完成。
addCallback()方法接受两个参数:一个是成功回调函数,另一个是失败回调函数。当Future对象的计算成功完成时,成功回调函数会被自动执行;当计算失败时,失败回调函数会被自动执行。回调函数可以是任何实现了接口ListenableFutureCallback的类的实例。
使用addCallback()方法可以方便地处理异步计算的结果,避免了手动检查Future对象的状态并等待计算完成的繁琐操作。同时,回调函数的执行是在异步计算完成后自动执行的,不会阻塞当前线程,提高了程序的并发性能。
需要注意的是,addCallback()方法只能用于Guava库中的ListenableFuture对象,而不能用于Java原生的Future对象。如果需要使用回调函数处理异步计算的结果,可以考虑使用Guava库中的ListenableFuture类。
完整代码
import com.alibaba.dubbo.common.threadpool.support.fixed.FixedThreadPool;
import com.google.common.util.concurrent.*;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.concurrent.*;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
TaskTest taskTest = new TaskTest();
taskTest.username = "123";
taskTest.password = "123";
// ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
//
// ListenableFuture<String> submit = pool.submit(taskTest);
// String s = submit.get();
TestFuture();
}
public static void TestThreadPool() throws ExecutionException, InterruptedException {
TaskTest taskTest = new TaskTest();
taskTest.username = "123";
taskTest.password = "123";
ExecutorService threadPool = Executors.newScheduledThreadPool(5);
Future<String> submit = threadPool.submit(taskTest);
String s = submit.get();
System.out.println(s);
threadPool.shutdown();
}
public static void TestThreadPoolExecutor(){
TaskTest taskTest = new TaskTest();
taskTest.username = "123";
taskTest.password = "123";
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
10,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(20));
ListeningExecutorService listeningPool = MoreExecutors.listeningDecorator(threadPoolExecutor);
ListenableFuture<String> submit = listeningPool.submit(taskTest);
//然而这个listen方法并不能有返回值
submit.addListener(new Runnable() {
@Override
public void run() {
System.out.println("方法submit已执行完毕");
}
},threadPoolExecutor);
//addlistener方法添加一个Runable的回调函数,当submit执行完毕之后,会调用第二个参数threadPoolExecutor的线程池执行这个回调函数
}
public static void TestFuture(){
TaskTest taskTest = new TaskTest();
taskTest.username = "123";
taskTest.password = "123";
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
10,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(20));
ListeningExecutorService listeningPool = MoreExecutors.listeningDecorator(threadPoolExecutor);
ListenableFuture<String> future = listeningPool.submit(taskTest);
/*
FutureCallBack接口可以对每个任务的成功或失败单独做出响应
*/
FutureCallback<String> futureCallback = new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("Futures.addCallback 能带返回值:" + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("出错,业务回滚或补偿");
}
};
//为任务绑定回调接口
Futures.addCallback(future, futureCallback, listeningPool);
}
}
class TaskTest implements Callable<String>{
String username;
String password;
@Override
public String call() throws Exception {
return "task" + username + password;
}
}
class TaskTest1 implements Runnable{
@Override
public void run() {
}
}
class TaskTest2 extends Thread{
@Override
public void run() {
}
}
都看到这了点个赞帮过下活动呗