이 기사에서는 springboot에서 멀티 스레드를 개발할 때 주의해야 할 사항에 대해 설명합니다. (요약) 도움이 필요한 친구들이 참고할 수 있을 만큼 참고할만한 가치가 있습니다.
springboot 기반의 멀티스레드 프로그램 개발 과정에서 springboot를 활용하기 위해서는 스프링 컨테이너 자체를 주입하여 관리해야 하기 때문입니다. 따라서 본 글에서는 두 가지를 결합하여 개발할 때 주의해야 할 사항을 기록하는 데 주로 사용된다.
첫 번째 단계는 관리를 위해 스레드 클래스의 인스턴스를 sping 컨테이너에 주입하는 것입니다
@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{ }
여기서 springboot @Import 주석을 사용하여 ThreadConfig에서 스캔한 패키지에 @와 같은 주석이 달린 예제를 주입합니다. Component 등을 컨테이너에 넣습니다.
그런 다음 스레드가 시작됩니다. 내 비즈니스 시나리오에는 두 가지 상황이 있습니다.
1 프로그램이 실행되면 자동으로 시작됩니다.
이것은 일반 실행 프로그램에 있습니다. 물론 메인 실행에서 직접 코드를 통해 스레드를 시작할 수도 있습니다. 하지만 springboot에서는 @PostConstruct 주석을 사용하여 Bean 컨테이너에 주입된 스레드 객체가 자동으로 시작되도록 할 수 있습니다
@Component public class demoThread extends Thread { //注意这里,如果你没有实现把多线程类的实例注入到spring容器中,这里你是无法拿到其他自动装配的对象实例的的,这也是我们第一步的意义所在。 @Autowired private XxxService xxxService; @PostConstruct public void start() { super.start(); } public void run() { // Ok,在这里你就可以实现线程要实现的功能逻辑了,自然也可以直接使用装配好的sevice对象实例。 } }
2. 프로그램에서 스레드를 시작해야 할 때 시작합니다. 물론 이 경우 스레드 클래스 인스턴스를 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<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 ThreadLocal<Integer> 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; } }
여기에 필요합니다. spirngboot에 TaskThread 스레드 클래스가 필요한지 여부에 주의하세요. 다중 인스턴스 모드 또는 기본 싱글톤 모드로 설정하려면 @Scope("prototype") 주석을 추가하세요.
싱글톤 모드에서는 SpringBootUtils.getBean(TaskThread.class)이 매번 동일한 객체를 반환하지만 매번 새로운 객체를 생성할 필요는 없지만 멤버 변수의 스레드 안전성은 보장할 수 없습니다. 스레드 풀의 실행 스레드는 해당 값을 공유합니다. 멀티 인스턴스 모드에서는 매번 새로운 스레드 개체가 생성되므로 위의 문제는 존재하지 않습니다.
위의 샘플 코드이든 일반 웹 개발이든 상관없이 spirngboot는 기본적으로 싱글톤 모드로 설정되어 있으며 스레드에 안전하지 않으며 ThreadLocal 또는 기타 동기식 처리를 통해 수행되어야 합니다.
각 스레드가 서로 영향을 주지 않고 서로 다른 값을 처리해야 하는 현재 비즈니스 시나리오로 돌아가서 @Scope("prototype") 주석을 통해 TaskThread를 다중 인스턴스 모드로 설정합니다.
Summary
위의 예를 통해 springboot와 멀티스레딩의 조합이 비교적 간단하다는 것을 알 수 있습니다. 구성을 통해 스프링 컨테이너에서 스레드 클래스를 관리할 수 있을 뿐만 아니라 스프링 컨테이너에서 객체 인스턴스도 사용할 수 있습니다. 스레드에서. 동시에 우리는 사용 중 스레드 안전 문제와 내부 작동 메커니즘 문제에 의식적으로 주의를 기울여야 합니다. 물론 여기에서의 이해는 여전히 상대적으로 간단합니다. 잘못된 점이 있으면 지적하고 설명해주세요.
위 내용은 springboot에서 멀티스레드를 개발할 때 주의해야 할 점은 무엇입니까? (요약)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!