Spring Boot教程十五:多執行緒
阿新 • • 發佈:2018-12-18
實際的開發應該開發過程中,經常需要使用到多執行緒,而且大多時候需要獲取到每個執行緒執行的結果,然後再執行剩下的業務邏輯。具體實現如下;
pom檔案引用:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
執行緒任務處理類;
package com.ganinfo.test; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Callable; /** * @author Shuyu.Wang * @package:com.ganinfo.test * @className: * @description: * @date 2018-10-28 19:35 **/ @Slf4j public class AuthCallable implements Callable { private AuthType authType; /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ @Override public Object call() throws Exception { if ("1".equals(authType.getType())){ log.info("方式一"+authType.getName()+"授權start"); Thread.sleep(8000); log.info("方式一授權end"); return authType.getName(); } if ("2".equals(authType.getType())){ log.info("方式二"+authType.getName()+"授權start"); Thread.sleep(7000); log.info("方式二授權end"); return authType.getName(); } if ("3".equals(authType.getType())){ log.info("方式三"+authType.getName()+"授權start"); Thread.sleep(5000); log.info("方式三授權end"); return authType.getName(); } if ("4".equals(authType.getType())){ log.info("方式四"+authType.getName()+"授權start"); Thread.sleep(3000); log.info("方式四授權end"); return authType.getName(); } if ("5".equals(authType.getType())){ log.info("方式五"+authType.getName()+"授權start"); Thread.sleep(1000); log.info("方式五授權end"); return authType.getName(); } return null; } public void setAuthType(AuthType authType) { this.authType = authType; } }
引用的POJO型別:
package com.ganinfo.test;
import lombok.Data;
/**
* @author Shuyu.Wang
* @package:com.ganinfo.test
* @className:
* @description:
* @date 2018-10-28 19:34
**/
@Data
public class AuthType {
private String type;
private String name;
}
業務實現類:
package com.ganinfo.test; import com.ganinfo.utils.GsonUtil; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.*; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author Shuyu.Wang * @package:com.ganinfo.test * @className: * @description: * @date 2018-10-28 19:41 **/ @Service @Slf4j public class AuthService { public void auth(String a) { long start=System.currentTimeMillis(); List<String> list = new ArrayList<>(); int count=5; try { final CountDownLatch countDownLatch = new CountDownLatch(count); ExecutorService executorService = Executors.newFixedThreadPool(8); ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService); for (int i = 1; i <= count; i++) { AuthCallable authCallable = new AuthCallable(); AuthType authType = new AuthType(); authType.setType(String.valueOf(i)); authType.setName(String.valueOf(i) + "名稱"); authCallable.setAuthType(authType); ListenableFuture listenableFuture = listeningExecutorService.submit(authCallable); Futures.addCallback(listenableFuture, new FutureCallback<String>() { @Override public void onSuccess(String name) { log.info("授權結果" + name); list.add(name); countDownLatch.countDown(); } @Override public void onFailure(Throwable throwable) { countDownLatch.countDown(); log.info("處理出錯:", throwable); } }); } try { executorService.shutdown(); //shutdown呼叫後,不可以再submit新的task,已經submit的將繼續執行。 if (!countDownLatch.await(15, TimeUnit.MINUTES)) { log.info("超時的時候向執行緒池中所有的執行緒發出中斷"); // 超時的時候向執行緒池中所有的執行緒發出中斷(interrupted)。 executorService.shutdownNow(); } } catch (InterruptedException e) { e.printStackTrace(); executorService.shutdownNow(); //shutdownNow試圖停止當前正執行的task,並返回尚未執行的task的list } log.info("執行結果" + GsonUtil.GsonString(list)); long end=System.currentTimeMillis(); log.info("用時" + (end-start)); } catch (Exception ex) { ex.printStackTrace(); } } }
執行結果如下:
2018-10-28 20:16:49.510 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-1] com.ganinfo.test.AuthCallable : 方式一1名稱授權start
2018-10-28 20:16:49.522 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-2] com.ganinfo.test.AuthCallable : 方式二2名稱授權start
2018-10-28 20:16:49.522 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-3] com.ganinfo.test.AuthCallable : 方式三3名稱授權start
2018-10-28 20:16:49.522 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-4] com.ganinfo.test.AuthCallable : 方式四4名稱授權start
2018-10-28 20:16:49.522 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-5] com.ganinfo.test.AuthCallable : 方式五5名稱授權start
2018-10-28 20:16:50.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-5] com.ganinfo.test.AuthCallable : 方式五授權end
2018-10-28 20:16:50.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-5] com.ganinfo.test.AuthService : 授權結果5名稱
2018-10-28 20:16:52.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-4] com.ganinfo.test.AuthCallable : 方式四授權end
2018-10-28 20:16:52.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-4] com.ganinfo.test.AuthService : 授權結果4名稱
2018-10-28 20:16:54.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-3] com.ganinfo.test.AuthCallable : 方式三授權end
2018-10-28 20:16:54.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-3] com.ganinfo.test.AuthService : 授權結果3名稱
2018-10-28 20:16:56.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-2] com.ganinfo.test.AuthCallable : 方式二授權end
2018-10-28 20:16:56.523 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-2] com.ganinfo.test.AuthService : 授權結果2名稱
2018-10-28 20:16:57.512 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-1] com.ganinfo.test.AuthCallable : 方式一授權end
2018-10-28 20:16:57.512 INFO [alarmservice1,,,] 34204 --- [ool-13-thread-1] com.ganinfo.test.AuthService : 授權結果1名稱
2018-10-28 20:16:57.515 INFO [alarmservice1,,,] 34204 --- [ main] com.ganinfo.test.AuthService : 執行結果["5名稱","4名稱","3名稱","2名稱","1名稱"]
2018-10-28 20:16:57.515 INFO [alarmservice1,,,] 34204 --- [ main] com.ganinfo.test.AuthService : 用時8013