线程中调用Spring管理的Bean,以及定时线程的问题

本文介绍了一个用于获取Spring Bean的工具类实现,并详细展示了如何在多线程环境中使用该工具类来周期性地调用服务层方法。文章还讨论了线程周期性调用的几种常见实现方式及其问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这需求还是比较正常的,尝试了外部用@Autowired注解引入Spring注解的Bean,然后以此为参数传入Thread中,发现报NULLPOINTER异常,于是放弃,而且要定义为static,多方尝试之后,用如下的方法的得以解决问题:

首先新建SpringBean的工具类

package com.hhu.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 创建获取SpringBean的工具类
 * @author Weiguo Liu
 *
 */
public class SpringBeanUtil implements ApplicationContextAware {
	private static ApplicationContext applicationContext = null;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringBeanUtil.applicationContext = applicationContext;
	}

	public static Object getBeanByName(String beanName) {
		if (applicationContext == null) {
			return null;
		}
		return applicationContext.getBean(beanName);
	}

	public static <T> T getBean(Class<T> type) {
		return applicationContext.getBean(type);
	}
}

这里需要注意是,工具类写完了一定要在spring的配置文件中注册,如果不注册的Spring无法感知,因为网上提供了一种直接获取Bean的方法,尝试后发现不管用,可能就是这方面的原因吧,

<!--配置SpringUtil的工具类  -->
	<bean id="springBeanUtil" class="com.hhu.util.SpringBeanUtil">
	</bean>

后面在线程中直接调用即可

SpringBeanUtil su = new SpringBeanUtil();
	
	public void run() {    
    	
    	while(true) {
    		StationService stationService = (StationService) su.getBeanByName("stationService");
    		System.out.println("当前线程:" + Thread.currentThread().getName());
    		Station station = stationService.getLastStation();
    		System.out.println("查询成功:" + station);
    		try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	
    }  

这里顺便记录一下,关于线程的周期性调用的问题,在网上找资料说是如下代码可以解决

ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
//第一个参数是执行的线程, 第二个参数为首次执行的延时时间(初始化时延),第三个参数为定时执行的间隔时间,最后一个是计时单位 
service.scheduleAtFixedRate(runnable, 5, 10, TimeUnit.SECONDS);

后来这么搞的,发现跑起来像脱缰的野马,参数完全不起作用,这与这个以后有时间在搞,附上我最后用的笨办法:

 /**
     * 建立连接后
     */
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("进入真正的握手类:MyWebSocketHandler,成功链接");
        //这里开启一个线程去扫数据库
        System.out.println("进行数据库扫描。。。。。");
        
        if(session.isOpen()) {//如果数据库会话是开着的状态
        	
            //第一个参数是执行的线程, 第二个参数为首次执行的延时时间(初始化时延),第三个参数为定时执行的间隔时间,最后一个是计时单位    
            //service.scheduleAtFixedRate(runnable, 5, 10, TimeUnit.SECONDS);
        	//System.out.println(sdf.format(new Date()));
        	//service.scheduleAtFixedRate(runnable ,10, 15, TimeUnit.SECONDS);
        	
        	//thread.start();
        	st.start();
        	
        }
        
    }

线程类如下:

class StationThread extends Thread {
	
	SpringBeanUtil su = new SpringBeanUtil();
	
	public void run() {    
    	
    	while(true) {
    		StationService stationService = (StationService) su.getBeanByName("stationService");
    		System.out.println("当前线程:" + Thread.currentThread().getName());
    		Station station = stationService.getLastStation();
    		System.out.println("查询成功:" + station);
    		try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
    	}
    	
    }  
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值