spring boot整合redis,以及设置缓存过期时间
spring-boot 整合 redis,有问题,欢迎留言
注:redis服务器要先开启! 或者连接远程服务器上的 Redis,但是依然要开启服务,不然会一直 TimeOut!
pom文件:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
配置 application.properties
# redis
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000
配置文件写完之后基础环境也算是已经搭建好了,开始测试使用 Test
接下来 我们测试上代码:
//注入redisTemplate @Autowired private StringRedisTemplate redisTemplate; @Test public void setRedis() {
//缓存中最常用的方法 redisTemplate.opsForValue().set("first","siwei");
//设置缓存过期时间为30 单位:秒
//关于TimeUnit下面有部分源码截图 redisTemplate.opsForValue().set("second","siweiWu",30, TimeUnit.SECONDS); System.out.println("存入缓存成功"); } @Test public void getRedis(){ String first = redisTemplate.opsForValue().get("first"); String second = redisTemplate.opsForValue().get("second"); System.out.println("取出缓存中first的数据是:"+first); System.out.println("取出缓存中second的数据是:"+second); } @Test public void delRedis() { //根据key删除缓存 Boolean first1 = redisTemplate.delete("first"); System.out.println("是否删除成功:"+first1); }
附上日常项目中使用的服务层的 Redis 五种(String,Hash,List,Set,ZSet)常用的方法,可以直接拷贝使用,自行导包噢~
创建 RedisService 服务类
import org.springframework.data.redis.core.ListOperations; import java.util.List; import java.util.Set; /** * @author wusw * @date 2020/4/16 13:11 */ public interface RedisService { /** * 添加 key:string 缓存 * * @param key key * @param value value * @param time time * @return */ boolean cacheValue(String key, String value, long time); /** * 添加 key:string 缓存 * * @param key key * @param value value * @return */ boolean cacheValue(String key, String value); /** * 根据 key:string 判断缓存是否存在 * * @param key key * @return boolean */ boolean containsValueKey(String key); /** * 判断缓存 key:set集合 是否存在 * * @param key key * @return */ boolean containsSetKey(String key); /** * 判断缓存 key:list集合 是否存在 * * @param key key * @return boolean */ boolean containsListKey(String key); /** * 查询缓存 key 是否存在 * @param key key * @return true/false */ boolean containsKey(String key); /** * 根据 key 获取缓存value * * @param key key * @return value */ String getValue(String key); /** * 根据 key 移除 value 缓存 * * @param key key * @return true/false */ boolean removeValue(String key); /** * 根据 key 移除 set 缓存 * * @param key key * @return true/false */ boolean removeSet(String key); /** * 根据 key 移除 list 缓存 * * @param key key * @return true/false */ boolean removeList(String key); /** * 缓存set操作 * * @param key key * @param value value * @param time time * @return boolean */ boolean cacheSet(String key, String value, long time); /** * 添加 set 缓存 * * @param key key * @param value value * @return true/false */ boolean cacheSet(String key, String value); /** * 添加 缓存 set * * @param k key * @param v value * @param time 时间 * @return */ boolean cacheSet(String k, Set<String> v, long time); /** * 缓存 set * @param k key * @param v value * @return */ boolean cacheSet(String k, Set<String> v); /** * 获取缓存set数据 * @param k key * @return set集合 */ Set<String> getSet(String k); /** * list 缓存 * @param k key * @param v value * @param time 时间 * @return true/false */ boolean cacheList(String k, String v, long time); /** * 缓存 list * @param k key * @param v value * @return true/false */ boolean cacheList(String k, String v); /** * 缓存 list 集合 * @param k key * @param v value * @param time 时间 * @return */ boolean cacheList(String k, List<String> v, long time); /** * 缓存 list * @param k key * @param v value * @return true/false */ boolean cacheList(String k, List<String> v); /** * 根据 key 获取 list 缓存 * @param k key * @param start 开始 * @param end 结束 * @return 获取缓存区间内 所有value */ List<String> getList(String k, long start, long end); /** * 根据 key 获取总条数 用于分页 * @param key key * @return 条数 */ long getListSize(String key); /** * 获取总条数 用于分页 * @param listOps =redisTemplate.opsForList(); * @param k key * @return size */ long getListSize(ListOperations<String, String> listOps, String k); /** * 根据 key 移除 list 缓存 * @param k key * @return */ boolean removeOneOfList(String k); }
创建 RedisServiceImpl 实现 RedisService 接口
import com.technologies.bear.service.RedisService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.SetOperations; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @author wusw * @date 2020/4/16 13:11 */ @Service public class RedisServiceImpl implements RedisService { /** * slf4j 日志 */ private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * 自定义 key 三种 * String key:String value 普通key:value * String key:Set<String> set key:set集合 * String key:List<String> list key:list集合 */ private static final String KEY_PREFIX_KEY = "info:bear:key"; private static final String KEY_PREFIX_SET = "info:bear:set"; private static final String KEY_PREFIX_LIST = "info:bear:list"; private final RedisTemplate<String, String> redisTemplate; /** * 注入 * @param redisTemplate 模板 */ @Autowired public RedisServiceImpl(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } /** * 添加 key:string 缓存 * * @param k key * @param v value * @param time time * @return */ @Override public boolean cacheValue(String k, String v, long time) { try { String key = KEY_PREFIX_KEY + k; ValueOperations<String, String> ops = redisTemplate.opsForValue(); ops.set(key, v); if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Throwable e) { log.error("缓存存入失败key:[{}] value:[{}]", k, v); } return false; } /** * 添加 key:string 缓存 * * @param key key * @param value value * @return */ @Override public boolean cacheValue(String key, String value) { return cacheValue(key, value, -1); } /** * 根据 key:string 判断缓存是否存在 * * @param key key * @return boolean */ @Override public boolean containsValueKey(String key) { return containsKey(KEY_PREFIX_KEY + key); } /** * 判断缓存 key:set集合 是否存在 * * @param key key * @return */ @Override public boolean containsSetKey(String key) { return containsKey(KEY_PREFIX_SET + key); } /** * 判断缓存 key:list集合 是否存在 * * @param key key * @return boolean */ @Override public boolean containsListKey(String key) { return containsKey(KEY_PREFIX_LIST + key); } /** * 查询缓存 key 是否存在 * @param key key * @return true/false */ @Override public boolean containsKey(String key) { try { return redisTemplate.hasKey(key); } catch (Throwable e) { log.error("判断缓存存在失败key:[" + key + "],错误信息 Codeor[{}]", e); } return false; } /** * 根据 key 获取缓存value * * @param key key * @return value */ @Override public String getValue(String key) { try { ValueOperations<String, String> ops = redisTemplate.opsForValue(); return ops.get(KEY_PREFIX_KEY + key); } catch (Throwable e) { log.error("根据 key 获取缓存失败,当前key:[{}],失败原因 Codeor:[{}]", key, e); } return null; } /** * 缓存set操作 * * @param k key * @param v value * @param time time * @return boolean */ @Override public boolean cacheSet(String k, String v, long time) { try { String key = KEY_PREFIX_SET + k; SetOperations<String, String> opsForSet = redisTemplate.opsForSet(); opsForSet.add(key, v); if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Throwable e) { log.error("缓存 set 失败 当前 key:[{}] 失败原因 [{}]", k, e); } return false; } /** * 添加 set 缓存 * * @param key key * @param value value * @return true/false */ @Override public boolean cacheSet(String key, String value) { return cacheSet(key, value, -1); } /** * 添加 缓存 set * * @param k key * @param v value * @param time 时间 * @return */ @Override public boolean cacheSet(String k, Set<String> v, long time) { try { String key = KEY_PREFIX_SET + k; SetOperations<String, String> opsForSet = redisTemplate.opsForSet(); opsForSet.add(key, v.toArray(new String[v.size()])); if (time > 0){ redisTemplate.expire(key,time,TimeUnit.SECONDS); } return true; } catch (Throwable e) { log.error("缓存 set 失败 当前 key:[{}],失败原因 [{}]", k, e); } return false; } /** * 缓存 set * @param k key * @param v value * @return */ @Override public boolean cacheSet(String k, Set<String> v) { return cacheSet(k,v,-1); } /** * 获取缓存set数据 * @param k key * @return set集合 */ @Override public Set<String> getSet(String k) { try { String key = KEY_PREFIX_SET + k; SetOperations<String, String> opsForSet = redisTemplate.opsForSet(); return opsForSet.members(key); }catch (Throwable e){ log.error("获取缓存set失败 当前 key:[{}],失败原因 [{}]", k, e); } return null; } /** * list 缓存 * @param k key * @param v value * @param time 时间 * @return true/false */ @Override public boolean cacheList(String k, String v, long time) { try { String key = KEY_PREFIX_LIST + k; ListOperations<String, String> opsForList = redisTemplate.opsForList(); //此处为right push 方法/ 也可以 left push .. opsForList.rightPush(key,v); if (time > 0){ redisTemplate.expire(key,time,TimeUnit.SECONDS); } return true; }catch (Throwable e){ log.error("缓存list失败 当前 key:[{}],失败原因 [{}]", k, e); } return false; } /** * 缓存 list * @param k key * @param v value * @return true/false */ @Override public boolean cacheList(String k, String v) { return cacheList(k,v,-1); } /** * 缓存 list 集合 * @param k key * @param v value * @param time 时间 * @return */ @Override public boolean cacheList(String k, List<String> v, long time) { try { String key = KEY_PREFIX_LIST + k; ListOperations<String, String> opsForList = redisTemplate.opsForList(); opsForList.rightPushAll(key,v); if (time > 0){ redisTemplate.expire(key,time,TimeUnit.SECONDS); } return true; }catch (Throwable e){ log.error("缓存list失败 当前 key:[{}],失败原因 [{}]", k, e); } return false; } /** * 缓存 list * @param k key * @param v value * @return true/false */ @Override public boolean cacheList(String k, List<String> v) { return cacheList(k,v,-1); } /** * 根据 key 获取 list 缓存 * @param k key * @param start 开始 * @param end 结束 * @return 获取缓存区间内 所有value */ @Override public List<String> getList(String k, long start, long end) { try { String key = KEY_PREFIX_LIST + k; ListOperations<String, String> opsForList = redisTemplate.opsForList(); return opsForList.range(key,start,end); }catch (Throwable e){ log.error("获取list缓存失败 当前 key:[{}],失败原因 [{}]", k, e); } return null; } /** * 根据 key 获取总条数 用于分页 * @param key key * @return 条数 */ @Override public long getListSize(String key) { try { ListOperations<String, String> opsForList = redisTemplate.opsForList(); return opsForList.size(KEY_PREFIX_LIST + key); }catch (Throwable e){ log.error("获取list长度失败key[" + KEY_PREFIX_LIST + key + "], Codeor[" + e + "]"); } return 0; } /** * 获取总条数 用于分页 * @param listOps =redisTemplate.opsForList(); * @param k key * @return size */ @Override public long getListSize(ListOperations<String, String> listOps, String k) { try { return listOps.size(k); }catch (Throwable e){ log.error("获取list长度失败key[" + KEY_PREFIX_LIST + k + "], Codeor[" + e + "]"); } return 0; } /** * 根据 key 移除 list 缓存 * @param k key * @return */ @Override public boolean removeOneOfList(String k) { try { String key = KEY_PREFIX_LIST + k; ListOperations<String, String> opsForList = redisTemplate.opsForList(); opsForList.rightPop(key); return true; }catch (Throwable e){ log.error("移除list缓存失败 key[" + KEY_PREFIX_LIST + k + "], Codeor[" + e + "]"); } return false; } /** * 根据 key 移除 value 缓存 * * @param key key * @return true/false */ @Override public boolean removeValue(String key) { return remove(KEY_PREFIX_KEY + key); } /** * 根据 key 移除 set 缓存 * * @param key key * @return true/false */ @Override public boolean removeSet(String key) { return remove(KEY_PREFIX_SET + key); } /** * 根据 key 移除 list 缓存 * * @param key key * @return true/false */ @Override public boolean removeList(String key) { return remove(KEY_PREFIX_LIST + key); } /** * 移除缓存 * * @param key key * @return boolean */ private boolean remove(String key) { try { redisTemplate.delete(key); return true; } catch (Throwable e) { log.error("移除缓存失败 key:[{}] 失败原因 [{}]", key, e); } return false; } }
注:其他 Service 层使用时,只需要将 RedisService 注入即可像普通Service层一样调用
StringRedisTemplate相关方法我也总结了一下,可能不是很全 不过还是够用了
上面设置缓存过期时间的TimeUnit源码 部分截图说明(后面会附上全部的源码——总390行,我就折叠一下了):
先上截图
TimeUnit全部源码:
1 /* 2 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 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 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/publicdomain/zero/1.0/ 34 */ 35 36 package java.util.concurrent; 37 38 /** 39 * A {@code TimeUnit} represents time durations at a given unit of 40 * granularity and provides utility methods to convert across units, 41 * and to perform timing and delay operations in these units. A 42 * {@code TimeUnit} does not maintain time information, but only 43 * helps organize and use time representations that may be maintained 44 * separately across various contexts. A nanosecond is defined as one 45 * thousandth of a microsecond, a microsecond as one thousandth of a 46 * millisecond, a millisecond as one thousandth of a second, a minute 47 * as sixty seconds, an hour as sixty minutes, and a day as twenty four 48 * hours. 49 * 50 * <p>A {@code TimeUnit} is mainly used to inform time-based methods 51 * how a given timing parameter should be interpreted. For example, 52 * the following code will timeout in 50 milliseconds if the {@link 53 * java.util.concurrent.locks.Lock lock} is not available: 54 * 55 * <pre> {@code 56 * Lock lock = ...; 57 * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre> 58 * 59 * while this code will timeout in 50 seconds: 60 * <pre> {@code 61 * Lock lock = ...; 62 * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre> 63 * 64 * Note however, that there is no guarantee that a particular timeout 65 * implementation will be able to notice the passage of time at the 66 * same granularity as the given {@code TimeUnit}. 67 * 68 * @since 1.5 69 * @author Doug Lea 70 */ 71 public enum TimeUnit { 72 /** 73 * Time unit representing one thousandth of a microsecond 74 */ 75 NANOSECONDS { 76 public long toNanos(long d) { return d; } 77 public long toMicros(long d) { return d/(C1/C0); } 78 public long toMillis(long d) { return d/(C2/C0); } 79 public long toSeconds(long d) { return d/(C3/C0); } 80 public long toMinutes(long d) { return d/(C4/C0); } 81 public long toHours(long d) { return d/(C5/C0); } 82 public long toDays(long d) { return d/(C6/C0); } 83 public long convert(long d, TimeUnit u) { return u.toNanos(d); } 84 int excessNanos(long d, long m) { return (int)(d - (m*C2)); } 85 }, 86 87 /** 88 * Time unit representing one thousandth of a millisecond 89 */ 90 MICROSECONDS { 91 public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); } 92 public long toMicros(long d) { return d; } 93 public long toMillis(long d) { return d/(C2/C1); } 94 public long toSeconds(long d) { return d/(C3/C1); } 95 public long toMinutes(long d) { return d/(C4/C1); } 96 public long toHours(long d) { return d/(C5/C1); } 97 public long toDays(long d) { return d/(C6/C1); } 98 public long convert(long d, TimeUnit u) { return u.toMicros(d); } 99 int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); } 100 }, 101 102 /** 103 * Time unit representing one thousandth of a second 104 */ 105 MILLISECONDS { 106 public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); } 107 public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); } 108 public long toMillis(long d) { return d; } 109 public long toSeconds(long d) { return d/(C3/C2); } 110 public long toMinutes(long d) { return d/(C4/C2); } 111 public long toHours(long d) { return d/(C5/C2); } 112 public long toDays(long d) { return d/(C6/C2); } 113 public long convert(long d, TimeUnit u) { return u.toMillis(d); } 114 int excessNanos(long d, long m) { return 0; } 115 }, 116 117 /** 118 * Time unit representing one second 119 */ 120 SECONDS { 121 public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); } 122 public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); } 123 public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); } 124 public long toSeconds(long d) { return d; } 125 public long toMinutes(long d) { return d/(C4/C3); } 126 public long toHours(long d) { return d/(C5/C3); } 127 public long toDays(long d) { return d/(C6/C3); } 128 public long convert(long d, TimeUnit u) { return u.toSeconds(d); } 129 int excessNanos(long d, long m) { return 0; } 130 }, 131 132 /** 133 * Time unit representing sixty seconds 134 */ 135 MINUTES { 136 public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); } 137 public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); } 138 public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); } 139 public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); } 140 public long toMinutes(long d) { return d; } 141 public long toHours(long d) { return d/(C5/C4); } 142 public long toDays(long d) { return d/(C6/C4); } 143 public long convert(long d, TimeUnit u) { return u.toMinutes(d); } 144 int excessNanos(long d, long m) { return 0; } 145 }, 146 147 /** 148 * Time unit representing sixty minutes 149 */ 150 HOURS { 151 public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); } 152 public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); } 153 public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); } 154 public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); } 155 public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); } 156 public long toHours(long d) { return d; } 157 public long toDays(long d) { return d/(C6/C5); } 158 public long convert(long d, TimeUnit u) { return u.toHours(d); } 159 int excessNanos(long d, long m) { return 0; } 160 }, 161 162 /** 163 * Time unit representing twenty four hours 164 */ 165 DAYS { 166 public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); } 167 public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); } 168 public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); } 169 public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); } 170 public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); } 171 public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); } 172 public long toDays(long d) { return d; } 173 public long convert(long d, TimeUnit u) { return u.toDays(d); } 174 int excessNanos(long d, long m) { return 0; } 175 }; 176 177 // Handy constants for conversion methods 178 static final long C0 = 1L; 179 static final long C1 = C0 * 1000L; 180 static final long C2 = C1 * 1000L; 181 static final long C3 = C2 * 1000L; 182 static final long C4 = C3 * 60L; 183 static final long C5 = C4 * 60L; 184 static final long C6 = C5 * 24L; 185 186 static final long MAX = Long.MAX_VALUE; 187 188 /** 189 * Scale d by m, checking for overflow. 190 * This has a short name to make above code more readable. 191 */ 192 static long x(long d, long m, long over) { 193 if (d > over) return Long.MAX_VALUE; 194 if (d < -over) return Long.MIN_VALUE; 195 return d * m; 196 } 197 198 // To maintain full signature compatibility with 1.5, and to improve the 199 // clarity of the generated javadoc (see 6287639: Abstract methods in 200 // enum classes should not be listed as abstract), method convert 201 // etc. are not declared abstract but otherwise act as abstract methods. 202 203 /** 204 * Converts the given time duration in the given unit to this unit. 205 * Conversions from finer to coarser granularities truncate, so 206 * lose precision. For example, converting {@code 999} milliseconds 207 * to seconds results in {@code 0}. Conversions from coarser to 208 * finer granularities with arguments that would numerically 209 * overflow saturate to {@code Long.MIN_VALUE} if negative or 210 * {@code Long.MAX_VALUE} if positive. 211 * 212 * <p>For example, to convert 10 minutes to milliseconds, use: 213 * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)} 214 * 215 * @param sourceDuration the time duration in the given {@code sourceUnit} 216 * @param sourceUnit the unit of the {@code sourceDuration} argument 217 * @return the converted duration in this unit, 218 * or {@code Long.MIN_VALUE} if conversion would negatively 219 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 220 */ 221 public long convert(long sourceDuration, TimeUnit sourceUnit) { 222 throw new AbstractMethodError(); 223 } 224 225 /** 226 * Equivalent to 227 * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}. 228 * @param duration the duration 229 * @return the converted duration, 230 * or {@code Long.MIN_VALUE} if conversion would negatively 231 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 232 */ 233 public long toNanos(long duration) { 234 throw new AbstractMethodError(); 235 } 236 237 /** 238 * Equivalent to 239 * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}. 240 * @param duration the duration 241 * @return the converted duration, 242 * or {@code Long.MIN_VALUE} if conversion would negatively 243 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 244 */ 245 public long toMicros(long duration) { 246 throw new AbstractMethodError(); 247 } 248 249 /** 250 * Equivalent to 251 * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}. 252 * @param duration the duration 253 * @return the converted duration, 254 * or {@code Long.MIN_VALUE} if conversion would negatively 255 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 256 */ 257 public long toMillis(long duration) { 258 throw new AbstractMethodError(); 259 } 260 261 /** 262 * Equivalent to 263 * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}. 264 * @param duration the duration 265 * @return the converted duration, 266 * or {@code Long.MIN_VALUE} if conversion would negatively 267 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 268 */ 269 public long toSeconds(long duration) { 270 throw new AbstractMethodError(); 271 } 272 273 /** 274 * Equivalent to 275 * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}. 276 * @param duration the duration 277 * @return the converted duration, 278 * or {@code Long.MIN_VALUE} if conversion would negatively 279 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 280 * @since 1.6 281 */ 282 public long toMinutes(long duration) { 283 throw new AbstractMethodError(); 284 } 285 286 /** 287 * Equivalent to 288 * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}. 289 * @param duration the duration 290 * @return the converted duration, 291 * or {@code Long.MIN_VALUE} if conversion would negatively 292 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 293 * @since 1.6 294 */ 295 public long toHours(long duration) { 296 throw new AbstractMethodError(); 297 } 298 299 /** 300 * Equivalent to 301 * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}. 302 * @param duration the duration 303 * @return the converted duration 304 * @since 1.6 305 */ 306 public long toDays(long duration) { 307 throw new AbstractMethodError(); 308 } 309 310 /** 311 * Utility to compute the excess-nanosecond argument to wait, 312 * sleep, join. 313 * @param d the duration 314 * @param m the number of milliseconds 315 * @return the number of nanoseconds 316 */ 317 abstract int excessNanos(long d, long m); 318 319 /** 320 * Performs a timed {@link Object#wait(long, int) Object.wait} 321 * using this time unit. 322 * This is a convenience method that converts timeout arguments 323 * into the form required by the {@code Object.wait} method. 324 * 325 * <p>For example, you could implement a blocking {@code poll} 326 * method (see {@link BlockingQueue#poll BlockingQueue.poll}) 327 * using: 328 * 329 * <pre> {@code 330 * public synchronized Object poll(long timeout, TimeUnit unit) 331 * throws InterruptedException { 332 * while (empty) { 333 * unit.timedWait(this, timeout); 334 * ... 335 * } 336 * }}</pre> 337 * 338 * @param obj the object to wait on 339 * @param timeout the maximum time to wait. If less than 340 * or equal to zero, do not wait at all. 341 * @throws InterruptedException if interrupted while waiting 342 */ 343 public void timedWait(Object obj, long timeout) 344 throws InterruptedException { 345 if (timeout > 0) { 346 long ms = toMillis(timeout); 347 int ns = excessNanos(timeout, ms); 348 obj.wait(ms, ns); 349 } 350 } 351 352 /** 353 * Performs a timed {@link Thread#join(long, int) Thread.join} 354 * using this time unit. 355 * This is a convenience method that converts time arguments into the 356 * form required by the {@code Thread.join} method. 357 * 358 * @param thread the thread to wait for 359 * @param timeout the maximum time to wait. If less than 360 * or equal to zero, do not wait at all. 361 * @throws InterruptedException if interrupted while waiting 362 */ 363 public void timedJoin(Thread thread, long timeout) 364 throws InterruptedException { 365 if (timeout > 0) { 366 long ms = toMillis(timeout); 367 int ns = excessNanos(timeout, ms); 368 thread.join(ms, ns); 369 } 370 } 371 372 /** 373 * Performs a {@link Thread#sleep(long, int) Thread.sleep} using 374 * this time unit. 375 * This is a convenience method that converts time arguments into the 376 * form required by the {@code Thread.sleep} method. 377 * 378 * @param timeout the minimum time to sleep. If less than 379 * or equal to zero, do not sleep at all. 380 * @throws InterruptedException if interrupted while sleeping 381 */ 382 public void sleep(long timeout) throws InterruptedException { 383 if (timeout > 0) { 384 long ms = toMillis(timeout); 385 int ns = excessNanos(timeout, ms); 386 Thread.sleep(ms, ns); 387 } 388 } 389 390 }
本文为个人原创作品
身体很重要,在你40岁之前千万不要让它垮掉,因为 你是唯一
body is important. Don't let it break down before you are 40, because you are the only one