创建线程的几种方式

Thread

  • 普通写法

		Thread thread = new Thread() {
			@Override
			public void run() {
				System.out.println("hello");
			}
		};
		thread.start();
		

Thread类实现了Runnable接口,必须重写run方法.run方法并不是开启该线程,必须执行了start方法,才能运行该线程,运行即为运行run方法中的内容。

  • lambda表达式写法

		new Thread(() -> System.out.println("hello")).start();
		
  • FutureTask

		FutureTask<Integer> futureTask = new FutureTask(() -> 100);
		new Thread(futureTask).start();
		System.out.println(futureTask.get());
		

FutureTask是一个实现了RunnableFuture接口的类,它可以用来包装一个Callable或Runnable对象,作为一个异步任务来执行。FutureTask可以被提交给一个Executor来执行,并且可以查询任务的执行状态或取消任务的执行。
通过FutureTask,你可以在一个单独的线程中执行一个任务,并且在需要时获取任务的执行结果

ScheduledExecutorService(延迟任务)

ScheduledExecutorService是一个接口,它提供了一种调度任务在指定时间或以固定频率执行的方法。可以使用ScheduledExecutorService来创建一个线程池,并使用schedule()或scheduleAtFixedRate()等方法安排任务的执行。这对于需要按计划执行的周期性任务非常有用。

	
	private final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);


	/**
	 * 延时任务
	 * 参数1:任务
	 * 参数2:方法第一次执行的延迟时间
	 * 参数3:延迟单位
	 * 说明:延迟任务,只执行一次(不会再次执行),参数2为延迟时间
	 */
	@GetMapping("/x")
	private void x() {
		scheduledThreadPool.schedule(() -> System.out.println("hello"), 5, TimeUnit.SECONDS);
	}

	/**
	 * 循环任务,按照上一次任务的发起时间计算下一次任务的开始时间
	 * 参数1:任务
	 * 参数2:初始化完成后延迟多长时间执行第一次任务
	 * 参数3:任务时间间隔
	 * 参数4:单位
	 * 说明:如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行,如果你的任务执行时间超过间隔时间,那么任务时间间隔参数将无效,任务会不停地循环执行,该方法不能严格保证任务按一定时间间隔执行。
	 */
	@GetMapping("/xx")
	private void xx() {
		scheduledThreadPool.scheduleAtFixedRate(() -> System.out.println("hello"), 0, 2, TimeUnit.SECONDS);
	}

	/**
	 * 循环任务,以上一次任务的结束时间计算下一次任务的开始时间
	 * 参数1:任务
	 * 参数2:初始化完成后延迟多长时间执行第一次任务
	 * 参数3:任务执行时间间隔
	 * 参数4:单位
	 * 说明:以上一次任务执行结束时间为准,加上任务时间间隔作为下一次任务开始时间,该方法可以严格按照时间间隔执行
	 */
	@GetMapping("/xxx")
	private void xxx() {
		scheduledThreadPool.scheduleWithFixedDelay(() -> System.out.println("hello"), 0, 2, TimeUnit.SECONDS);
	}
	

详情参考 ScheduledExecutorService详解

CompletableFuture(异步任务)

CompletableFuture是一个用于处理异步任务的工具类,可以使用自定义线程池,如果使用指定线程池,默认情况下CompletableFuture会使用公共的ForkJoinPool.commonPool()线程池
详细参考
异步返回值需要等待任务执行完毕后才能获取返回结果,所以多个异步任务时一定要注意先调用完方法以后再操作返回对象,以免造成方法是同步执行的。

  • 单任务执行

	/**
	 * 创建一个不带返回值得任务(默认线程池)。
	 */
	CompletableFuture<Void> f1 = CompletableFuture.runAsync(new Runnable() {
	     @Override
	     public void run() {
	      //业务逻辑          
	     }
	 });
	 /**
	  * 创建一个带返回值的任务(默认线程池)。
	  */
	CompletableFuture<String> f2 = CompletableFuture.supplyAsync(new Supplier<String>() {
	    @Override
	    public String get() {
	        //业务逻辑
	        return null;
	    }
	});
	
  • 多任务返回值

		//创建线程池
		ExecutorService executor = Executors.newFixedThreadPool(10);
		// 任务1
		CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 1, executor);
		// 任务2
		CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 2, executor);
		// 任务3
		CompletableFuture<Integer> f3 = CompletableFuture.supplyAsync(() -> 3, executor);
		// 创建一个map用于接收三个任务的结果
		Map<String, Integer> map = CompletableFuture.allOf(f1, f2, f3).thenApply(v ->
				new HashMap<String, Integer>() {{
					try {
						put("task_1", f1.get());
						put("task_2", f2.get());
						put("task_3", f3.get());
					} catch (InterruptedException | ExecutionException e) {
						throw new RuntimeException(e);
					}
				}}).join();
				

ScheduledExecutorService与CompletableFuture差别

CompletableFuture还提供了一些其他方法,例如allOf()、anyOf()等,用于处理多个异步任务的结果。
综上所述,ScheduledExecutorService适用于调度和执行按计划执行的任务,而CompletableFuture适用于处理异步操作的结果。你可以根据具体的需求选择使用哪个并发工具。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值