My Octopress Blog

A blogging framework for hackers.

Quartz学习

| Comments

quartz是用于定时任务的组件, 可以用在j2se,j2ee. 在quartz里面,主要有以下核心组件.

  • Job, 这是只有一个excute()方法的接口,任务代码写在这里.

  • JobDetail, 这是用于实例化Job的类,在quartz里面,把Job和配置信息分开,是一大特色.比如在JobDetail里面,可以使用JobDataMap存放Job的运行状态. 用JobBuilder实例JobDetail.

  • Trigger, 一般和Job绑定在一起,定义Job的触发时间.使用TriggerBuilder实例Trigger.

  • Scheduler负责整个定时任务跑起来,通过Scheduler sche = StdSchedulerFactory.getDefaultScheduler();实例化,使用sche.start()开始任务,sche.shutdow()结束任务.

下面是基础的示例代码

一个简单的任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

public class HelloJob implements Job {

  @Override
  public void execute(JobExecutionContext arg0) throws JobExecutionException {
      JobKey key = arg0.getJobDetail().getKey();获取该job的唯一标识 name+group
      
      JobDataMap dataMap = arg0.getJobDetail().getJobDataMap();
      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");
      System.err.println("Instance " + key + "says: " + jobSays + ", and val is: " + myFloatValue);
      
  }

}

在上面的代码中,先定义一个简单的Job,然后能过JobExecutionContext这个上下文类,可以获得job时,绑定的一些参数和状态.

简单的任务执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;

public class SimpleJob {

    public static void main(String[] args) {

        try {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").usingJobData("jobSays", "Hello World!").usingJobData("myFloatValue", 3.141f).build();
            Trigger trigger = newTrigger().withIdentity("myTrigger", "group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(10).repeatSecondlyForTotalCount(5, 10)).build();


            scheduler.start();
            scheduler.scheduleJob(job, trigger);
            Thread.sleep(60000);
            scheduler.shutdown();

        } catch (SchedulerException se) {
            se.printStackTrace();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
    }
}

上面代码中,示例如何创建JobDetial, Trigger, Scheduer.如何使用JobDataMap

Js中的单例模式

| Comments

其实从一些基础语言来看一些编程模式,会看得更清楚一些。如在js中也是有开发者模式, 构造函数模式, 单例模式,下面就记录下学习的单例模式过程。 其实js中的模式只是通过代码来模拟,比如单例模式可以通过以下代码来模拟.

example code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function MySingletonClass() {
  if (arguments.callee._singletonInstance) {
      return arguments.callee._singletonInstance;
  };
  arguments.callee._singletonInstance = this;

  this.Foo = function(name) {
      console.log(name);
  };

  this.test = function() {
      console.log("s");
  }
}
var a = new MySingletonClass();
var b = new MySingletonClass();
console.log(a == b);//这里返回的是true,所以验证了单例的实现

以上代码最重要的是arguments.callee这个内置对象,这个对象其实在函数内部而代表该函数本身,mdn上的解释

这里为什么要使用arguments.callee可以实现这个功能?

arguments.callee对于每个函数都会有只有一个,而且对这个对象加上属性不会影响到函数本身,如上面的代码arguments.callee._singletonInstance,虽然加上了_singletonInstance 这个属性,但是打印出a,或者b对象的时候,会发现根本没有 _singletonInstance 这个属性.

setTimout, setInterval in Javascript, 同步与异步

| Comments

setTimeout: 让程序进入等候队列,暂缓执行,但是后续方法会继续执行

Use setTimeoutmdn上的解释
1
2
3
4
var interval = 1000;
setTimeout(function(){
  console.log("ya, timeout");
}, interval*2);//隔2ms后执行

setInterval: 让程序进入循环操作,但是程序是异步执行

Use setTimeoutmdn上的解释
1
2
3
4
var interval = 1000;
setInterval(function(){
  console.log("ya, timeout");
}, interval*2);//每2ms执行一次,异步

怎么证明setInterval里面的代码会是异步执行?

怎么证明setInterval里面的代码会是异步执行
1
2
3
4
5
6
7
8
9
10
11
//假如不是异步执行,会看到aa计时器会以8ms递增.但是实际的情况是aa在第一次不是2ms,后面都是2ms递增
var interval = 1000;
console.time("aa");
setInterval(function(){
  (function  my_async_function(){
      setTimeout(function(){
          console.log("test");
          console.timeEnd("aa");
      },interval*6);
  })();
},2000);

应该怎么解决这个问题?

应该怎么解决这个问题
1
2
3
4
5
6
7
8
9
10
11
12
13
//在这里面,我们通过setTimeout加上回调方法来解决这个问题
//运行程序,会发现bb计时器会完美的以11ms递增,实现了单线的执行程序且循环执行
var interval = 1000;
console.time("bb");
(function  schedule()  {
  setTimeout(function  do_it()  {
      setTimeout(function() {
          console.log("async content");
          schedule();
          console.timeEnd("bb");
      }, interval*6);
  }, interval*5);
}());