创建定时任务
//禁止使用Timer,一律使用ScheduledExecutorService
ScheduledExecutorService schedule =
new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("scheduled-%d").build());
// 创建并执行在给定延迟后启用的一次性操作
schedule.schedule(new DemoWorker(), 60000L, TimeUnit.MILLISECONDS);
/*
* 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
* 也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
*/
schedule.scheduleAtFixedRate(new DemoWorker(), 60000L, 60000L, TimeUnit.MILLISECONDS);
// 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
schedule.scheduleWithFixedDelay(new DemoWorker(), 60000L, 60000L, TimeUnit.MILLISECONDS);
创建线程池
// 创建线程工厂实例
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
// 创建线程池,核心线程数、最大线程数、空闲保持时间、队列长度、拒绝策略可自行定义
ExecutorService pool = new ThreadPoolExecutor(5, 20, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
线程池关闭
ExecutorService pool=...;
pool.shutdown(); //用于线程内无迭代,且预期在短时间内能执行完毕的线程任务;
pool.shutdownNow();//用于线程内有迭代逻辑,或执行完成时间无法预估的场景(此类线程任务代码必须进行中断信号的处理);
• 中断异常处理:
//所有会引起中断异常的代码段都要单独处理中断异常,绝对不可合并在Exception或Throwable里处理;并根据代码结构和业务逻辑判断,是否需要恢复中断异常
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
// 中断处理
} catch (Exception e) {
// 其它异常处理
}
库代码中断异常处理
//库代码中断异常处理主要有两种方式,如下:
1 传递InterruptedException:避开这个异常通常是最明智的策略——只需将InterruptedException传递给方法的调用者。
2 恢复中断:有时不能抛出InterruptedException,例如代码位于Runnable中时。在这些情况下,捕获InterruptedException并使用当前线程上的Interrupt方法恢复中断状态,这样在调用栈中更高层的代码将看到引发了一个中断。
检查中断状态
Thread.interrupted(); //测试当前线程是否已经中断。线程的中断状态 由该方法清除。
Thread.currentThread().isInterrupted(); //测试线程是否已经中断。线程的中断状态不受该方法的影响。
• 线程内有迭代逻辑时的中断处理参考代码模板:
// 迭代必须包含对中断信号的响应,以及对中断异常的处理
while (线程中断状态为false) {
// 业务代码
}
int listSize = 100;
for (int i = 0; i < listSize; i++) {
if (线程中断状态为false) {
break;
}
// 业务代码
}
建议:CountDownLatch实现所有线程达到某一个目标后,再继续进行下一步工作
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
ExecutorService executor = new ThreadPoolExecutor(5, 20, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
int count = 500;
//CountDownLatch的计数器需要和任务数相同,执行完一个任务调用countDown让计数器减一
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
executor.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(50);
System.out.println("运行任务");
} catch (Exception e) {
e.printStackTrace();
}
latch.countDown();
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("都运行完了");
采用Lock加锁在finally块中释放锁,保证不论是否抛出异常锁一定会被释放
Lock lock = new ReentrantLock();
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "得到了锁");
System.out.println("do something...");
} catch (Exception e) {
System.out.println("handle exception");
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + "释放了锁");
}
读取文件为流
byte[] fileBytes = org.apache.commons.io.FileUtils.readFileToByteArray(new File("fileName"));
写入字节流到文件
org.apache.commons.io.FileUtils.writeByteArrayToFile(new File("fileName"), fileBytes);
commons-io中用一行代码实现文件读写操作
private static void readFile() {
try {
List<String> lines = org.apache.commons.io.FileUtils.readLines(new File("D:\\rowkey.txt"));
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeFile() {
List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
try {
org.apache.commons.io.FileUtils.writeLines(new File("D:\\id.txt"), list, true);
} catch (IOException e) {
e.printStackTrace();
}
}
获取环境变量
System.getenv("PATH");
System.getenv("JAVA_HOME");
获取路径
HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
String contextPath=request.getContextPath();
//URL
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/";