真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

springboot中多線程開發(fā)的注意事項(xiàng)總結(jié)

前言

創(chuàng)新互聯(lián)公司是一家專注于網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),皇姑網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:皇姑等地區(qū)?;使米鼍W(wǎng)站價(jià)格咨詢:13518219792

Springt通過任務(wù)執(zhí)行器(TaskExecutor)來實(shí)現(xiàn)多線程和并發(fā)編程。使用ThreadPoolTaskExecutor可實(shí)現(xiàn)一個(gè)基于線程池的TaskExecutor。而實(shí)際開發(fā)中任務(wù)一般是非阻礙的,即異步的,所以我們要在配置類中通過@EnableAsync 開啟對(duì)異步任務(wù)的支持,并通過實(shí)際執(zhí)行Bean的方法中使用@Async注解來聲明其是一個(gè)異步任務(wù)。

基于springboot的多線程程序開發(fā)過程中,由于本身也需要注入spring容器進(jìn)行管理,才能發(fā)揮springboot的優(yōu)勢(shì)。所以這篇文字主要用來記錄開發(fā)中兩者結(jié)合時(shí)需要注意的一些事項(xiàng)。

注意事項(xiàng)

第一步我們把線程類的實(shí)例注入sping容器進(jìn)行管理

@Configuration
@SpringBootApplication
@Import({ThreadConfig.class})
public class ThreadApp implements CommandLineRunner
{
 public static void main(String[] args) throws Exception {

  ApplicationContext app = SpringApplication.run(ThreadApp .class, args);
  //這里主要保存上下文對(duì)象實(shí)例,需要加上。SpringBootUtils類網(wǎng)上很多,可以自己搜下
  SpringBootUtils.setApplicationContext(app);

 }

 //access command line arguments
 @Override
 public void run(String... args) throws Exception {
  //do something
 }
}

//ComponentScan注解會(huì)掃描com.demo.thead下,也就是多線程類所在的包下的文件
@Configuration
@ComponentScan(basePackages = { "com.demo.thread"})
public class ThreadConfig{

}

這里使用springboot @Import 注解,把ThreadConfig里掃描到的包中帶注解的示例,如@Component等注入到spring容器當(dāng)中.

然后是線程的啟動(dòng),這里在我的業(yè)務(wù)場(chǎng)景中有兩種情況:

1、程序運(yùn)行時(shí),自動(dòng)啟動(dòng);

這在一般的可執(zhí)行程序里面,當(dāng)然可以直接在main函數(shù)里執(zhí)行通過代碼啟動(dòng)線程。但在springboot中,我們可以使用@PostConstruct注解的方式,讓已經(jīng)注入bean容器的線程對(duì)象自啟動(dòng)

@Component
public class demoThread extends Thread
{
 //注意這里,如果你沒有實(shí)現(xiàn)把多線程類的實(shí)例注入到spring容器中,這里你是無法拿到其他自動(dòng)裝配的對(duì)象實(shí)例的的,這也是我們第一步的意義所在。
 @Autowired
 private XxxService xxxService;

 @PostConstruct
 public void start() {
  super.start();
 }

 public void run() {
  // Ok,在這里你就可以實(shí)現(xiàn)線程要實(shí)現(xiàn)的功能邏輯了,自然也可以直接使用裝配好的sevice對(duì)象實(shí)例。
  
 }
}

 2、在程序中,需要開啟線程時(shí)啟動(dòng),比如在從kafka接收數(shù)據(jù),開啟線程處理,當(dāng)然這種情況下也需要通過第一步,把線程類實(shí)例注入到sping容器中

private TaskThread thread;
 private ExecutorService taskPool= new ThreadPoolExecutor(
   5, 10, 1000,
   TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10),
   new ThreadPoolExecutor.CallerRunsPolicy()); 


 @KafkaListener(topics = "xxTopic")
 public void receive(ConsumerRecord consumerRecord) {
   JSONObject json = JSON.parseObject(consumerRecord.value().toString());
   //通過SpringBootUtils獲取線程類的實(shí)例
   thread = SpringBootUtils.getBean(TaskThread.class);
   //啟動(dòng)線程
   //new Thread(thread).start() ; 
   //向線程對(duì)象里傳值
   thread.init(i);
   //放入線程池執(zhí)行
   taskPool.execute(thread);

 }
//注意這里是否添加@Scope("prototype")注解
@Component
@Scope("prototype")
public class TaskThread implements Runnable{
 
 protected int value=0;

 @Autowired
 private XxxService xxxService;
 
 //ThreadLocal 對(duì)象,單例模式下可以保證成員變量的線程安全和獨(dú)立性。
 public ThreadLocal valueLocal = new ThreadLocal < Integer > () {
  @Override
  protected Integer initialValue() {
   return 0;
  }
 };

 protected static final Logger LOG = LoggerFactory.getLogger(GpsTaskThread.class);
 
 @Override
 public final void run() {
  try { 
   LOG.info(value+"");
   
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 public void init(int Value) {
  this.value=Value;
 }
}

在這里我們需要注意,TaskThread這個(gè)線程類在spirngboot中是否要添加@Scope("prototype")注解設(shè)置為多例模式還是默認(rèn)單例模式。

在單例模式下SpringBootUtils.getBean(TaskThread.class) 每次返回的都是同一個(gè)對(duì)象,雖然不需要每次都創(chuàng)建新的對(duì)象,但無法保證成員變量的線程安全,也就是說在線程池中的執(zhí)行的線程,它們的value值是共享的。而多例模式下,由于每次創(chuàng)建的都是一個(gè)新的線程對(duì)象,則不存在上述問題。

所以在這里請(qǐng)大家注意無論是我上面的示例代碼還是平常的web開發(fā)中,spirngboot默認(rèn)為單例模式,自定義的成員變量是線程不安全的,需要通過ThreadLocal 或這其他方法做同步處理。

回到我們當(dāng)前的業(yè)務(wù)場(chǎng)景,在這里我們需要每個(gè)線程處理的value值不同,互不影響,那么通過@Scope("prototype")注解把TaskThread設(shè)置為多例模式。

總結(jié)

通過上面的示例,我們可以看到springboot與多線程的結(jié)合還是比較簡(jiǎn)單,通過配置,我們既可以在spring容器中管理線程類,也可以在線程中使用sping容器中的對(duì)象實(shí)例。同時(shí)我們?cè)谑褂玫倪^程當(dāng)中要有意識(shí)的去注意線程安全方面的問題和內(nèi)部運(yùn)行機(jī)制的問題。當(dāng)然這里理解的還是比較淺顯,如果有不正確的地方還請(qǐng)大家指出與海涵。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。


本文題目:springboot中多線程開發(fā)的注意事項(xiàng)總結(jié)
文章轉(zhuǎn)載:http://weahome.cn/article/ijiicc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部