java线程创建的三种方式及线程状态

 Java 天生就是多线程,主线程main,GC线程、分发处理jvm信号线程等。

1. 线程创建的三种方式 : 

   1.1 通过继承Thread,重写run方法

   1.2 实现runable接口

   1.3 实现Callable接口

tips: 

   1.Thread 与Runable关系,Thread实现了Runable接口,并提供入参为Runable引用的构造器,以实现静态代理模式。

   2. Callable接口 :配合ExecutorService、Future可实现程序的异步任务及超时控制,异步回调等功能。

下面列举超时控制的一种实现方式  : 

以下列举了同步第三方数据超时控制的简要程序。


/**
 * Author:		Velen
 * Created Date: 2017-12-06 13:45
 */
@Service("realTimeSynApi")
public class RealTimeSynApi {

    private static final Logger LOG = LoggerFactory.getLogger(RealTimeSynApi.class);

    @Autowired
    private RedisService redisService;

    @Autowired
    private IntegrationFactory integrationFactory;

    /**
     * 用于业务接口实时同步api信息,利用redis根据casNo计数,控制每个casNo每天只同步一次,且设置超时时限
     * @param casNo
     * @param custId
     * @param timeOutLimit  单位毫秒
     * @return
     */
    public Boolean synApiDataInfo(String casNo,String custId,Long timeOutLimit) {
        if (StringUtils.isBlank(casNo)) {
            return false;
        }
        Long currentValue = getCounterNum(casNo);
        if (null != currentValue && currentValue.intValue() >= 1) {
            return false;
        }
        Boolean result = true;
        if (null != timeOutLimit && timeOutLimit.intValue()>0) {
            String resultCode = timerSynApi(casNo,custId,timeOutLimit);
            if (JobResultCode.FAILURE.toString().equals(resultCode) || JobResultCode.TIME_OUT.toString().equals(resultCode)) {
                result = false;
            }
        } else {
            result = integrationFactory.synSingleCasInfo(casNo,custId);
        }
        if (!result) {
            return false;
        }
        try {
            //计数+1,失效时间 1 天
            incrCounter(casNo,1L);
            setExpireTime(casNo,1L);
        } catch (Exception e) {
            LOG.error("RealTimeSynApi synApiDataInfo redis error!",e);
            return false;
        }
        return true;
    }

    /**
     * 超时控制同步API信息
     * @param casNo
     * @param custId
     * @return
     */
   private String timerSynApi(String casNo,String custId,Long timeOutLimit) {
       final SynApiDataJob job = new SynApiDataJob(casNo,custId);
       final ExecutorService exec = Executors.newFixedThreadPool(1);
       String resultCode = "";
       try {
           Future<String> future = exec.submit(job);
           String obj = future.get(timeOutLimit, TimeUnit.MILLISECONDS); //任务处理超时时间设为 1 秒
           resultCode = obj;
           LOG.info("任务处理结果",obj);
       } catch (TimeoutException ex) {
           resultCode = JobResultCode.TIME_OUT.toString();
           /**目前业务需求无法满足1s返回结果,超时异常暂不打印,该场景需要时可打开**/
           /*LOG.error("业务调用API任务处理超时",ex);*/
           /*ex.printStackTrace();*/
       } catch (Exception e) {
           resultCode = JobResultCode.FAILURE.toString();
           LOG.error("任务处理异常!",e);
           e.printStackTrace();
       }
       exec.shutdown();
       return resultCode;
   }


    /**
     * 同步API数据job类
     */
   class SynApiDataJob implements Callable<String>{

        private String casNo = null;

        private String custId = null;

       public SynApiDataJob(String casNo, String custId) {
           this.casNo = casNo;
           this.custId = custId;
       }

       @Override
       public String call() throws Exception {
           if (integrationFactory.synSingleCasInfo(this.casNo,this.custId)) {
               return JobResultCode.SUCCESS.toString();
           } else {
               return JobResultCode.FAILURE.toString();
           }
       }
   }

    /**
     * 处理结果枚举类
     */
   enum JobResultCode {

       SUCCESS("处理完成"),
       FAILURE("处理失败"),
       TIME_OUT("处理超时");

       private String desc;

       JobResultCode(String desc) {
           this.desc = desc;
       }

       public String getDesc() {
           return desc;
       }
   }


    /**
     * 获取计数器当前值
     * @param key
     * @return
     */
    public Long getCounterNum(String key) {
        return redisService.getRedisClient().getNoIncr(key);
    }

    /**
     * 计数增加
     * @param key
     * @param value
     * @return
     */
    public Long incrCounter(String key, Long value) {
        return redisService.getRedisClient().incr(key,value);
    }

    /**
     * 设置失效时间
     * @param key
     * @param value
     */
    public void setExpireTime(String key,long value) {
        redisService.getRedisClient().expire(key, value, TimeUnit.DAYS);
    }

    /**
     * 删除当前计数器
     * @param key
     */
    public void resetCounter(String key) {
        redisService.deleteCache(key);
    }

}

 

2. 线程状态转换 : 


3. 线程的几种常见api  : 

 3.1  join()  : 

       join 可以看做线程之间协作的一种方式,有些业务场景需要两个线程按照一定规则处理,B需要在某个节点依赖A线程后再携手并进。此时就需要使用到join(),thradA.join(),此时B线程会等待A线程执行终止后再继续执行.

3.2 sleep():

   按照一定时间休眠。需要注意sleep()方法如果当前线程已经获得了锁,sleep不会释放锁.

sleep() VS wait()

两者主要的区别:

  1. sleep()方法是Thread的静态方法,而wait是Object实例方法
  2. wait()方法必须要在同步方法或者同步块中调用,也就是必须已经获得对象锁。而sleep()方法没有这个限制可以在任何地方种使用。另外,wait()方法会释放占有的对象锁,使得该线程进入等待池中,等待下一次获取资源。而sleep()方法只是会让出CPU并不会释放掉对象锁;
  3. sleep()方法在休眠时间达到后如果再次获得CPU时间片就会继续执行,而wait()方法必须等待Object.notift/Object.notifyAll通知后,才会离开等待池,并且再次获得CPU时间片才会继续执行


3.3 yield() : 

     一旦执行此方法,代表当前线程将让出时间片,让出不代表当前线程不再执行,如果让出后该线程在竞争中再次获得时间片,则会继续执行。需要注意的是,该方法让出的时间片只能供相同优先级的线程竞争。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值