In diesem Artikel erfahren Sie, worauf Sie bei der Entwicklung von Multithreads unter Springboot achten müssen. (Zusammenfassung), es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen.
Im Entwicklungsprozess von Multithread-Programmen auf Basis von Springboot können die Vorteile von Springboot nur genutzt werden, weil der Spring-Container selbst zur Verwaltung injiziert werden muss. Daher wird dieser Artikel hauptsächlich dazu verwendet, einige Dinge aufzuzeichnen, auf die bei der Kombination der beiden während der Entwicklung geachtet werden muss.
Im ersten Schritt injizieren wir die Instanz der Thread-Klasse zur Verwaltung in den Sping-Container
@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); //这里主要保存上下文对象实例,需要加上。SpringBootUtils类网上很多,可以自己搜下 SpringBootUtils.setApplicationContext(app); } //access command line arguments @Override public void run(String... args) throws Exception { //do something } } //ComponentScan注解会扫描com.demo.thead下,也就是多线程类所在的包下的文件 @Configuration @ComponentScan(basePackages = { "com.demo.thread"}) public class ThreadConfig{ }
Hier verwenden wir den Springboot @ Importieren Sie Annotationen und scannen Sie die ThreadConfig-Beispiele mit Annotationen im Paket, z. B. @Component usw., die in den Spring-Container eingefügt werden.
Dann wird der Thread gestartet. In meinem Geschäftsszenario gibt es zwei Situationen:
1 Wenn das Programm ausgeführt wird, wird es automatisch gestartet.
Dies ist ein allgemeines ausführbares Programm, das natürlich direkt in der Hauptfunktion ausgeführt werden kann, um den Thread zu starten. Aber in Springboot können wir die Annotation @PostConstruct verwenden, um dem Thread-Objekt, das in den Bean-Container injiziert wurde, den automatischen Start zu ermöglichen
@Component public class demoThread extends Thread { //注意这里,如果你没有实现把多线程类的实例注入到spring容器中,这里你是无法拿到其他自动装配的对象实例的的,这也是我们第一步的意义所在。 @Autowired private XxxService xxxService; @PostConstruct public void start() { super.start(); } public void run() { // Ok,在这里你就可以实现线程要实现的功能逻辑了,自然也可以直接使用装配好的sevice对象实例。 } }
2. Im Das Programm muss beim Öffnen des Threads gestartet werden, z. B. um Daten von Kafka zu empfangen und die Thread-Verarbeitung zu starten. Natürlich müssen Sie in diesem Fall auch den ersten Schritt ausführen und die Thread-Klasseninstanz in den Sping-Container einfügen
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<Object, Object> consumerRecord) { JSONObject json = JSON.parseObject(consumerRecord.value().toString()); //通过SpringBootUtils获取线程类的实例 thread = SpringBootUtils.getBean(TaskThread.class); //启动线程 //new Thread(thread).start() ; //向线程对象里传值 thread.init(i); //放入线程池执行 taskPool.execute(thread); }
//注意这里是否添加@Scope("prototype")注解 @Component @Scope("prototype") public class TaskThread implements Runnable{ protected int value=0; @Autowired private XxxService xxxService; //ThreadLocal 对象,单例模式下可以保证成员变量的线程安全和独立性。 public ThreadLocalc0f559cc8d56b43654fcbe4aa9df7b4a valueLocal = new ThreadLocal 46fc8f240055341038a5bc0c386009d9 () { @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; } }
Hier müssen wir darauf achten, ob die TaskThread-Thread-Klasse mit der Annotation @Scope("prototype") hinzugefügt werden soll spirngboot, um es auf den Mehrfachinstanzmodus oder den Standard-Singleton-Modus einzustellen.
Im Singleton-Modus gibt SpringBootUtils.getBean(TaskThread.class) jedes Mal dasselbe Objekt zurück. Obwohl nicht jedes Mal ein neues Objekt erstellt werden muss, kann der Thread der Mitgliedsvariablen nicht garantiert werden . Sicherheit, das heißt, die Werte der Ausführungsthreads im Thread-Pool werden gemeinsam genutzt. Da im Multiinstanzmodus jedes Mal ein neues Thread-Objekt erstellt wird, besteht das oben genannte Problem nicht.
Achten Sie hier also bitte darauf, ob es sich um meinen Beispielcode oben oder um die normale Webentwicklung handelt, Spirngboot verwendet standardmäßig den Singleton-Modus und benutzerdefinierte Mitgliedsvariablen sind threadunsicher. Es muss eine Synchronisierung durchgeführt werden über ThreadLocal oder andere Methoden.
Zurück zu unserem aktuellen Geschäftsszenario: Hier muss jeder Thread unterschiedliche Werte verarbeiten, ohne sich gegenseitig zu beeinflussen, und dann den TaskThread über das Annotationsmodell @Scope("prototype") auf mehrere Instanzen festlegen .
Zusammenfassung
Anhand des obigen Beispiels können wir sehen, dass die Kombination von Springboot und Multithreading relativ einfach ist. Durch die Konfiguration können wir Thread-Klassen im Spring-Container und auch in Threads verwalten . Verwenden Sie die Objektinstanz im Sping-Container. Gleichzeitig müssen wir während des Gebrauchs bewusst auf Thread-Sicherheitsprobleme und interne Betriebsmechanismusprobleme achten. Natürlich ist das Verständnis hier immer noch relativ einfach. Wenn etwas nicht stimmt, weisen Sie bitte darauf hin und erklären Sie es.
Das obige ist der detaillierte Inhalt vonWorauf sollten wir bei der Entwicklung von Multithreads unter Springboot achten? (Zusammenfassen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!