天天看点

Java:多线程异步并发

1、Java多线程实现

A.继承Thread类,重写run方法
@Test
public void threadTest() {
   Thread thread = new myThread();
   thread.start();
}

public class myThread extends Thread {
   @Override
   public void  run(){
       System.out.println("Thread create");
   } 
}
           

通过继承Thread 重写run方法,其中run()方法的方法体代表了线程需要完成的任务,称之为线程执行体。通过调用线程对象引用的start()方法,使得该线程进入到就绪状态。

B.实现Runnable接口,重写run方法。
@Test
public void runnableTest() {
   Runnable runnable = new MyRunnable();
   Thread thread = new Thread(runnable);
   thread.start();
}

public class MyRunnable implements Runnable{

   @Override
   public void run() {
       System.out.println("MyRunnable create");
   }
}
           

创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。

C.通过Callable和FutureTask创建线程
@Test
public void callableTest() throws ExecutionException, InterruptedException {
   Callable<Integer> myCallable = new MyCallable();    // 创建MyCallable对象
   FutureTask<Integer> ft = new FutureTask<Integer>(myCallable);
   Thread thread = new Thread(ft);
   thread.start();

   int result = ft.get();//当前是阻塞
}

public class MyCallable implements Callable<Integer>{

   @Override
   public Integer call() throws Exception {
       System.out.println("MyCallable create");
       return 0;
   }
}
           

在实现Callable接口中,此时不再是run()方法了,而是call()方法,此call()方法作为线程执行体,同时还具有返回值!在创建新的线程时,是通过FutureTask来包装MyCallable对象,同时作为了Thread对象的target。

D.通过线程池创建线程

Executors类:提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口

I.newSingleThreadExecutor

创建一个单线程化的Executor

@Test
public void executeSingleTest() {
   Runnable runnable = new MyRunnable();
   ExecutorService  executorService = Executors.newSingleThreadExecutor();
   executorService.submit(runnable);
}
           

II.newCachedThreadPool

创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

@Test
public void executeCacheTest() {
   Runnable runnable = new MyRunnable();
   ExecutorService  executorService = Executors.newCachedThreadPool();
   executorService.submit(runnable);
}
           

III.newScheduledThreadPool

创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

@Test
public void executeScheduledTest() {
   Runnable runnable = new MyRunnable();
   ExecutorService  executorService = Executors.newScheduledThreadPool(10);
   executorService.submit(runnable);
}
           

IIII.newFixedThreadPool

创建固定数目线程的线程池。

@Test
public void executeFixedTest() {
   Runnable runnable = new MyRunnable();
   ExecutorService  executorService = Executors.newFixedThreadPool(10);
   executorService.submit(runnable);
}
           

2、CompletableFuture 异步并发

JAVA8 CompletableFuture能够将回调放到与任务不同的线程中执行,也能将回调作为继续执行的同步函数,在与任务相同的线程中执行。它避免了传统回调最大的问题,那就是能够将控制流分离到不同的事件处理器中。

@Test
public void completableFutureTest() throws ExecutionException, InterruptedException {
   ExecutorService  executorService = Executors.newFixedThreadPool(100);
   CompletableFuture<String> future1 = CompletableFuture.supplyAsync(()->{
       System.out.println("查询图片");
       return "image_path";
   });

   CompletableFuture<String> future2 = CompletableFuture.supplyAsync(()->{
       System.out.println("查询商品");
       return "product";
   });

   CompletableFuture<String> future3 = CompletableFuture.supplyAsync(()->{
       System.out.println("查询SKU");
       return "SKU";
   });

   //等待所有的运行完成,返回
   CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2, future3);
   allOf.get();

   //任何一个执行完成,返回
   CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3);
   anyOf.get();
}
           

详细使用参考文档:https://www.jianshu.com/p/dff9063e1ab6