1. 继承Thread
public class TestDemo {
public static void main(String[] args) {
System.out.println("main...start....");
new Thread01().start();
System.out.println("main...end....");
}
/**
* 继承Thread
*/
public static class Thread01 extends Thread {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
}
}
}
2. 实现Runnable接口
public class TestDemo {
public static void main(String[] args) {
System.out.println("main...start....");
new Thread(new Runnable01()).start();
System.out.println("main...end....");
}
/**
* 实现Runnable接口
*/
public static class Runnable01 implements Runnable{
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
}
}
}
3. 实现Callable接口 + FutureTask
public class TestDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
FutureTask<Integer> task = new FutureTask<>(new Callable01());
new Thread(task).start();
//阻塞式等待
System.out.println("main...end...." + task.get());
}
/**
* 实现Callable接口 + FutureTask
*/
public static class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 0;
}
}
}
实现Callable接口的好处在于可以接收返回结果,如果需要使用线程的返回结构会阻塞等待
上面的三种方法,每次执行一个任务就需要开启一个线程,如果在高并发状态下,系统资源很快就会被耗尽,所以在实际使用中推荐使用线程池来实现异步任务
4. 线程池
通过线程池创建异步任务比较重要,所以接下来会详细说明,使用线程池可以有一下的好处
// 带缓存的线程池,可以灵活回收线程
ExecutorService pool1 = Executors.newCachedThreadPool();
// 固定大小的线程池
ExecutorService pool2 = Executors.newFixedThreadPool(10);
// 定时任务的线程池
ScheduledExecutorService pool3 = Executors.newScheduledThreadPool(10);
// 单线程的线程池,从队列中获取任务挨个执行
ExecutorService pool4 = Executors.newSingleThreadExecutor();
通过原生的方式创建线程池,需要了解线程池的7大参数
int corePoolSize:核心线程数,线程池创建好以后准备就绪的线程数,
int maximumPoolSize:最大线程数,控制资源
long keepAliveTime:存活时间,线程空闲时间超过设定的值,该线程就会被释放
TimeUnit unit:时间单位
BlockingQueue workQueue:阻塞队列,将多余的任务放在队列中等待执行
ThreadFactory threadFactory:线程的创建工厂,
RejectedExecutionHandler handler:当队列满了后,按照指定的拒绝策略拒绝执行任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
200,
10,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
在使用线程池进行异步任务之前还需要了解一个类—CompletableFuture
例如我们在执行一个功能时,需要去执行多个小任务,如果使用异步的方式,只需要等待最长的一个执行完,那么整个任务就执行完了,但是小任务之间又有逻辑上的关联,就可以使用CompletableFuture异步编排
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
//无返回值的异步方法
CompletableFuture.runAsync(()->{
System.out.println("当前线程:" + Thread.currentThread().getId());
},pool);
//有返回值的异步方法
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 0;
}, pool);
System.out.println(future.get());
System.out.println("main...end....");
}
}
2)、计算完成时回调方法大概有下面四种方法,其中whenComplete可以处理正常和异常的结果,而exceptionally只处理异常的结果
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
//有返回值的异步方法
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 10 / 0;
}, pool).whenComplete((result, exception) -> {//完成之后的逻辑
System.out.println("结果是" + result);
System.out.println("异常是" + exception);
}).exceptionally(throwable -> {//出现异常的逻辑
System.out.println("抛出异常,请及时处理");
return 10;
});
System.out.println("main...end....");
}
}
whenComplete只是感知上一步是否成功,它不能修改返回结果,如果要修改返回结果可以使用exceptionally,也可以使用另一种方法handle
3)、handle方法
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 10 / 2;
}, pool).handle((result, exception) -> {
if (result != null) {
System.out.println("执行成功");
return 1;
}
if (exception != null) {
System.out.println("执行异常");
return 0;
}
return -1;
});
System.out.println("main...end...." + future.get());
}
}
4)、线程串行方法,就是将需要执行的线程就行排序,先执行谁,然后将它执行的结果给下一个线程使用,进行有序执行
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 10 / 2;
}, pool).thenRun(() -> {//thenRun系列的方法不能获取上一步的执行结果,并且无返回值
System.out.println("执行任务2");
});
CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 10 / 2;
}, pool).thenAccept(result -> {//能接受上一步的返回结果,但是没有返回值
System.out.println("执行任务3并获取到上一步的结果为:" + result);
});
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
return 10 / 2;
}, pool).thenApply((result) -> {//既能就收上一步的结果,也能返回值
System.out.println("执行任务4并获取到上一步的结果为:" + result);
return 100;
});
System.out.println("任务4的返回结果:" + future.get());
System.out.println("main...end....");
}
}
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程1:" + Thread.currentThread().getId());
return 10 / 2;
}, pool);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程2:" + Thread.currentThread().getId());
return "hello";
}, pool);
//任务1和2执行完成后执行任务3,不能就收其他任务的返回值
future01.runAfterBoth(future02, () -> {
System.out.println("任务线程3:" + Thread.currentThread().getId());
});
System.out.println("**********************************************分割线**********************************************");
//任务1和2执行完成后执行任务4,并就收使用任务1和2的返回值,但是无返回值
future01.thenAcceptBoth(future02, (f1, f2) -> {
System.out.println("任务线程4:" + Thread.currentThread().getId());
System.out.println("获取到其他任务的返回值====>任务1:" + f1 + ",任务2:" + f2);
});
System.out.println("**********************************************分割线**********************************************");
//任务1和2执行完成后执行任务5,并就收使用任务1和2的返回值,有返回值
CompletableFuture<String> future = future01.thenCombine(future02, (f1, f2) -> {
System.out.println("任务线程5:" + Thread.currentThread().getId());
System.out.println("获取到其他任务的返回值====>任务1:" + f1 + ",任务2:" + f2);
return "任务5";
});
System.out.println("任务5的返回值:" + future.get());
System.out.println("main...end....");
}
}
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程1:" + Thread.currentThread().getId());
return 10 / 2;
}, pool);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程2:" + Thread.currentThread().getId());
return "hello";
}, pool);
System.out.println("**********************************************分割线**********************************************");
//当任务1或2执行完成后,执行任务3,不能接收返回值也不能返回值
future01.runAfterEither(future02, () -> {
System.out.println("任务线程3:" + Thread.currentThread().getId());
});
System.out.println("**********************************************分割线**********************************************");
//当任务1或2执行完成后,执行任务4,能接收返回值但不能返回值
future01.acceptEither(future02, (result) -> {
System.out.println("任务线程4:" + Thread.currentThread().getId());
System.out.println("就收到的上一步的返回值:" + result.toString());
});
System.out.println("**********************************************分割线**********************************************");
//当任务1或2执行完成后,执行任务5,能接收返回值也能返回值
CompletableFuture<String> future = future01.applyToEither(future02, (result) -> {
System.out.println("任务线程5:" + Thread.currentThread().getId());
System.out.println("就收到的上一步的返回值:" + result.toString());
return "任务5";
});
System.out.println("任务5执行完成后的结果:" + future.get());
System.out.println("main...end....");
}
}
public class TestDemo {
/**
* 创建一个固定大小的池对象,系统中不要太多的池,每个异步任务提交到池中运行
* 通过Executors工具类创建固定的线程池
*/
public static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start....");
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程1:" + Thread.currentThread().getId());
return 10 / 2;
}, pool);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程2:" + Thread.currentThread().getId());
return "hello";
}, pool);
CompletableFuture<Object> future03 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程3:" + Thread.currentThread().getId());
return "world";
}, pool);
CompletableFuture<Object> future04 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务线程4:" + Thread.currentThread().getId());
return 666;
}, pool);
System.out.println("**********************************************分割线**********************************************");
//所有任务都完成后才算完成
CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03, future04);
allOf.get();//阻塞等待所有结果完成
System.out.println(future01.get());
System.out.println(future02.get());
System.out.println(future03.get());
System.out.println(future04.get());
//当有一个执行完成就完成了
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03, future04);
anyOf.get();
System.out.println("线程返回结果:" + anyOf.get());
System.out.println("main...end....");
}
}