ThreadFactory线程工厂
生产线程的工厂,newThread是生产线程的方法,可以定义线程的基本特性。(比如优先级、是否守护线程)
join
调用join方法就会优先执行这个线程(thread1),等执行完毕后才会执行其他线程(thread执行完,再执行主线程)
public static void main(String[] args) throws InterruptedException { BaseThread baseThread = new BaseThread(); Thread thread1 = new Thread(baseThread); thread1.start(); //thread1执行完毕后才会执行主线程 thread1.join(); log.info("主线程第二个子线程开始执行------"); Thread thread2 = new Thread(baseThread); thread2.start(); }
锁
锁定部分代码,确保数据准确。配合和synchronized使用,弥补synchronized的不足。
//生成锁对象 Lock lock = new ReentrantLock(); @Override public void run() { //获取锁 lock.lock(); try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } finally { //释放锁 lock.unlock(); } System.out.println(Thread.currentThread().getName() + ": " + new Date()); }
Redis设置分布式锁
因为分布式系统使用synchronized和lock只能锁住单台服务器,这样无法确保分布式下这段逻辑准确。
@Autowired
private StringRedisTemplate stringRedisTemplate;
boolean isAccess = false;
String invoiceKey = String.format(ApiRedisKey.AGENT_WITHDRAW_INVOICE, req.getBaseUserId());
try {
//setIfAbsent 不存在就新增,存在就不改变原有的值。存在返回false,不存在返回true.
isAccess = stringRedisTemplate.opsForValue().setIfAbsent(invoiceKey, "1", 60, TimeUnit.SECONDS);
JlpayAssert.isTrue(isAccess, "正在处理,稍后再试");
//批处理ID(时间戳+用户ID)
String batchNo = System.currentTimeMillis() + String.format("%010d", req.getBaseUserId());
InvoiceVo invoiceVo = new InvoiceVo();
invoiceVo.setBatchNo(batchNo);
invoiceVo.setLicenseNo(getLicenseNo(req.getBaseUserId()));
HashMap<String, WithdrawChannelVo> channelMap = getChannelMap();
invoiceService.saveSubmitInvoice(req, channelMap, invoiceVo);
FixedThreadPoolUtil.INSTANCE.execute(() -> {
log.info("提现开票异步任务--开始");
ThreadContext.put("logid", ContextUtil.getThreadLogId());
//一般纳税人
List<WithdrawInvoice> withdrawInvoiceList = invoiceService.getWithdrawInvoiceList(batchNo, TaxType.GENERAL.code, "");
generalInvoice(batchNo, withdrawInvoiceList);
//小规模纳税人处理
HashMap<String, WithdrawChannelVo> smallScaleChannelMap = getSmallScaleChannel();
smallScaleInvoice(batchNo, smallScaleChannelMap);
log.info("提现开票异步任务--结束");
});
} finally {
if (isAccess) {
stringRedisTemplate.delete(invoiceKey);
}
}
run和start的区别
线程优先级
线程的优先级由1 -- 10 ,最低是1最高是10,优先级越高越可优先获取cpu去执行任务,但不绝对。
守护线程:
如果 JVM 中没有一个正在运行的非守护线程,这个时候,JVM 会退出。换句话说,守护线程拥有自动结束自己生命周期的特性,而非守护线程不具备这个特点。
//创建一个线程 public class DaemonThread implements Runnable { @SneakyThrows @Override public void run() { for (int i = 0; i < 10; i++) { Thread.sleep(100); log.info(Thread.currentThread().getName() + i); } } } //测试守护线程和非守护线程 public static void main(String[] args) throws InterruptedException { DaemonThread daemonThread = new DaemonThread(); Thread thread = new Thread(daemonThread, "daemon thread jason"); //true为守护线程:主线程结束,子线程也会结束 //默认false非守护线程:主线程结束,子线程还会继续执行 thread.setDaemon(true); thread.start(); for (int i = 0; i < 5; i++) { Thread.sleep(100); log.info(Thread.currentThread().getName() + i); } log.info("主线程结束---------"); }
主线程结束,守护线程就会结束,非守护线程依然会执行完毕。
标签:String,Thread,基础,线程,new,多线程,守护,log From: https://www.cnblogs.com/zhougongjin/p/17076248.html