Web项目中简单的多线程使用

**

Java多个线程同时访问操作单例对象,需不需要加锁的问题

** (1)多个线程处理单例对象的共有属性需加锁 ps:多个线程同时访问同一个方法,该方法操作了单例对象中共有(全局)的属性,则需要加锁。 (2)多个线程访问单例对象的同一方法,但该方法不处理共有属性则不需要加锁 (3)多个线程访问单例对象的static属性、方法需要加锁

结论: 操作共有属性,静态方法属性,加锁;只是调用方法,没有操作共有属性,不加锁。 方法中定义的局部变量在多线程下不会带来线程安全的问题。 **

线程的循环、休眠和停止

** public void testCron1() throws Exception { DateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”); log.info(sdf.format(new Date())+"*****每1秒执行一次"); Thread thread = Thread.currentThread(); while (!thread.isInterrupted()) { log.info(sdf.format(new Date())+“线程循环”); long now = (new Date()).getTime(); if((now%3 == 0)){ log.info(now+“线程停止”); thread.interrupt(); }else if ((now%2 == 0)) { log.info(now+“进入休眠状态”); thread.sleep(10000); } } } 注意:进入休眠状态再度循环的是while里的代码 **

Spring注入与多线程

** Spring不能在线程中注入,在线程中使用@Resource或者@Autowired注入全部为NULL 解决: 1、将需要注入的Bean在线程创建前就注入或者作为线程的构造函数参数传入

多线程定时器:

@Autowired
	private HsSchedulerMapper hsSchedulerMapper;
	@Autowired
	@Qualifier("ApplyAccount")private HsSchedule ApplyAccount;
	private ConfigResources cfg = new ConfigResources(HsjkClient.class.getResourceAsStream("/HS.properties"));
	private HttpClient client = new HttpClient();

	   //线程1
	   @Scheduled(cron="0/5 * * * * ? ")   //每4秒执行一次 
	    public void testCron6() {
	       DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
	       log.info(sdf.format(new Date())+"*********线程1执行一次");
		   ApplyAccount.scheduleTaskFirst(cfg, client, hsSchedulerMapper);
	    }
	   
	   //线程2
	   @Scheduled(cron="0/5 * * * * ? ")   //每4秒执行一次 
	    public void testCron7() {
		   DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
		   log.info(sdf.format(new Date())+"*********线程2执行一次");
		   ApplyAccount.scheduleTaskSecond(cfg, client, hsSchedulerMapper);
	    }

作为构造函数参数传入:

class Test{

    //这两个为线程所需要的Bean
    @Resource
    TestDao1 testDao1;

    @Resource
    TestDao2 testDao2;

    public void serviceExecute(){
        //在这里开启线程,执行操作
        ThreadExample te = new ThreadExample(TestDao1 testDao1,TestDao2 testDao2);
        te.start();
    }
    
    //内部类
    private class ThreadExample extends Thread{
		private TestDao1 testDao1 = null;
		private TestDao2 testDao2 = null;

        public ThreadExample(TestDao1 testDao1,TestDao2 testDao2){
            //也可以在构造函数中传入参数
            this.testDao1 = testDao1;
            this.testDao2 = testDao2;
        }
        public void run(){
            //这里为线程的操作
            //就可以使用注入之后Bean了
            testDao1.xxx();
            testDao2.xxx();
        }
    }
}

2、使用ApplicationContext.getBean方法来静态的获取Bean (摘抄自https://www.cnblogs.com/vinozly/p/5223147.html) (1)定义工具类

@Component 
public class SpringApplicationContextHolder implements ApplicationContextAware {  
  
    private static ApplicationContext context;  
  
    @Override  
    public void setApplicationContext(ApplicationContext context) throws BeansException {  
        SpringApplicationContextHolder.context = context;  
    }  
  
    public static Object getSpringBean(String beanName) {  
        notEmpty(beanName, "bean name is required");  
        return context==null?null:context.getBean(beanName);  
    }  
  
    public static String[] getBeanDefinitionNames() {  
        return context.getBeanDefinitionNames();  
    }

(2)线程中获取bean

UserRepo user = (UserRepo) SpringApplicationContextHolder.getSpringBean("userRepo");
经验分享 程序员 微信小程序 职场和发展