springboot整合springbatch和xxljob实现定时数据同步(完整代码)

news2024/11/15 16:37:57

springboot整合springbatch和xxljob实现定时数据同步(完整代码)

前言:公司一些老项目的定时任务使用spring自带的调度器来完成数据同步的,久而久之带来很多的不方便。首先没办法快速定位监控定时任务的执行情况,其次就是在做数据同步处理的时候,遇到业务比较复杂,数据量比较大的情况,会经常执行非常慢,超时导致定时任务执行失败。基于上诉的两种需求,公司决定将老项目的定时任务进行重构和迁移,然后我们组长架构选型是使用xxljob调度器和springbatch批处理两个轻量级框架,因为之前对springbatch不是很熟悉,趁此机会学习记录下。

之前我就写过文章springboot整合xxljob使用,现在是在此基础上再整合springbatch实现批处理逻辑,如果对xxljob不是很熟悉可以先看这个:https://blog.csdn.net/qq798867485/article/details/131423174

当然要使用xxljob首先要搭建任务调度中心,这个我也写过一篇文章:https://blog.csdn.net/qq798867485/article/details/131415408

言归正传,我们学习任意一个新技术,首先离不开官方文档,springbatch官方文档地址:https://docs.spring.io/spring-batch/docs/4.3.10/reference/html/

Spring Batch是一个轻量级的综合批处理框架,旨在实现对企业系统的日常运作至关重要的强大批处理应用的开发。Spring Batch不是一个调度框架。Spring Batch旨在与调度器一起工作,而不是取代调度器。

1. springbatch的基本
1.1 基础架构

在这里插入图片描述

这是springbatch的基本架构图,无论多复杂的业务都离不开这个架构。

在这里插入图片描述

在 Spring Batch 中,Job 只是一个 Step 实例的容器。 JobExecution是运行过程中实际发生的事情的主要存储机制,它包含了许多必须被控制和持久化的属性,JobExecution的ExecutionContext可以实现数据在不同Step传递.

在这里插入图片描述

每个 Job 完全由一个或多个步骤(step)组成。一个 Step 包含定义和控制实际批处理的所有必要信息.StepExecution的ExecutionContext是不可以在不同Step传递数据的。 ItemReader对一个 Step 的输入是对象是一个个读取, ItemProcessor也是对一个个item单独处理业务逻辑,而 ItemWriter每次都是一批或一大批的item来处理输出数据的。

1.2 数据表

springbatch有9张表,依赖包自己提供了相关的建表语句脚本,这些脚本位于 org.springframework.batch.core 包中。其中有六张表是比较重要的,我们可以通过这些表数据了解批处理的执行状态和结果,方便追踪日志,多次批处理等。

BATCH_JOB_INSTANCE :保存与 JobInstance 相关的所有信息,是整个层次结构的顶层

BATCH_JOB_EXECUTION_PARAMS:保存与 JobParameters 对象相关的所有信息。它包含传递给 Job 的 0 个或多个键/值对,可作为 job 运行时的参数记录。对于每个有助于生成 job 标识的参数,IDENTIFYING 标志都会被设置为 true

BATCH_JOB_EXECUTION:保存与 JobExecution 对象相关的所有信息。每次运行一个 Job 时,该表中总会有一个新的被称为 JobExecution 的对象和一行新记录。

BATCH_STEP_EXECUTION :保存与 StepExecution 对象相关的所有信息。该表在很多方面都与 BATCH_JOB_EXECUTION 表相似,每个 Step 创建的每个 JobExecution 总是至少有一个条目。

BATCH_JOB_EXECUTION_CONTEXT :保存与 Job ExecutionContext 相关的所有信息。每个 JobExecution 都有一个 Job ExecutionContext ,它包含特定 job 执行所需的所有 job 级数据。这些数据通常代表 job 失败后必须检索的状态,以便 JobInstance 可以 “从原处开始”。

BATCH_STEP_EXECUTION_CONTEXT :保存与 StepExecutionContext 相关的所有信息。每个 StepExecution 都有一个 ExecutionContext,它包含特定 step execution 需要持久化的所有数据。这些数据通常代表失败后必须检索的状态,以便 JobInstance 可以 “从原处开始”。

2. springboot整合springbatch
2.1 引入springbatch依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
</dependency>
2.2 在yml文件

关闭项目启动时,自动启动job,其次项目不配置数据库表自动生成,因为在启动项目之前,就在对应的数据库建好相关的表,建表脚本可以到org.springframework.batch.core取相关数据库的脚本,我这边使用的mysql数据库,对应的建表脚本如下

spring:
  batch:
    job:
      enabled: false

建表脚本:

-- Autogenerated: do not edit this file

CREATE TABLE BATCH_JOB_INSTANCE  (
   JOB_INSTANCE_ID BIGINT  NOT NULL PRIMARY KEY ,
   VERSION BIGINT ,
   JOB_NAME VARCHAR(100) NOT NULL,
   JOB_KEY VARCHAR(32) NOT NULL,
   constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ENGINE=InnoDB;

CREATE TABLE BATCH_JOB_EXECUTION  (
   JOB_EXECUTION_ID BIGINT  NOT NULL PRIMARY KEY ,
   VERSION BIGINT  ,
   JOB_INSTANCE_ID BIGINT NOT NULL,
   CREATE_TIME DATETIME(6) NOT NULL,
   START_TIME DATETIME(6) DEFAULT NULL ,
   END_TIME DATETIME(6) DEFAULT NULL ,
   STATUS VARCHAR(10) ,
   EXIT_CODE VARCHAR(2500) ,
   EXIT_MESSAGE VARCHAR(2500) ,
   LAST_UPDATED DATETIME(6),
   JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
   constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
   references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ENGINE=InnoDB;

CREATE TABLE BATCH_JOB_EXECUTION_PARAMS  (
   JOB_EXECUTION_ID BIGINT NOT NULL ,
   TYPE_CD VARCHAR(6) NOT NULL ,
   KEY_NAME VARCHAR(100) NOT NULL ,
   STRING_VAL VARCHAR(250) ,
   DATE_VAL DATETIME(6) DEFAULT NULL ,
   LONG_VAL BIGINT ,
   DOUBLE_VAL DOUBLE PRECISION ,
   IDENTIFYING CHAR(1) NOT NULL ,
   constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
   references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ENGINE=InnoDB;

CREATE TABLE BATCH_STEP_EXECUTION  (
   STEP_EXECUTION_ID BIGINT  NOT NULL PRIMARY KEY ,
   VERSION BIGINT NOT NULL,
   STEP_NAME VARCHAR(100) NOT NULL,
   JOB_EXECUTION_ID BIGINT NOT NULL,
   START_TIME DATETIME(6) NOT NULL ,
   END_TIME DATETIME(6) DEFAULT NULL ,
   STATUS VARCHAR(10) ,
   COMMIT_COUNT BIGINT ,
   READ_COUNT BIGINT ,
   FILTER_COUNT BIGINT ,
   WRITE_COUNT BIGINT ,
   READ_SKIP_COUNT BIGINT ,
   WRITE_SKIP_COUNT BIGINT ,
   PROCESS_SKIP_COUNT BIGINT ,
   ROLLBACK_COUNT BIGINT ,
   EXIT_CODE VARCHAR(2500) ,
   EXIT_MESSAGE VARCHAR(2500) ,
   LAST_UPDATED DATETIME(6),
   constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
   references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ENGINE=InnoDB;

CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT  (
   STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
   SHORT_CONTEXT VARCHAR(2500) NOT NULL,
   SERIALIZED_CONTEXT TEXT ,
   constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
   references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ENGINE=InnoDB;

CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT  (
   JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
   SHORT_CONTEXT VARCHAR(2500) NOT NULL,
   SERIALIZED_CONTEXT TEXT ,
   constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
   references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ENGINE=InnoDB;

CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
   ID BIGINT NOT NULL,
   UNIQUE_KEY CHAR(1) NOT NULL,
   constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

INSERT INTO BATCH_STEP_EXECUTION_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_STEP_EXECUTION_SEQ);

CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
   ID BIGINT NOT NULL,
   UNIQUE_KEY CHAR(1) NOT NULL,
   constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

INSERT INTO BATCH_JOB_EXECUTION_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_JOB_EXECUTION_SEQ);

CREATE TABLE BATCH_JOB_SEQ (
   ID BIGINT NOT NULL,
   UNIQUE_KEY CHAR(1) NOT NULL,
   constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

INSERT INTO BATCH_JOB_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_JOB_SEQ);
2.3 在启动类加上注解,保证springbatch的类被注入spring容器内
@EnableBatchProcessing
2.4 编写批处理作业进行

模拟一个场景,从文件中读取数据,同步到数据库表A,生成50万条数据

编写相关同步批处理作业

@Configuration
public class CsvToDbJobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    @Autowired
    private UserService userService;

    @Value("${job.data.path}")
    private String path;

    // 定义itemReader
    @Bean
    public FlatFileItemReader<User> csvToDbItemReader(){
        return new FlatFileItemReaderBuilder<User>()
                .name("csvToDbItemReader")
                .saveState(false)
                .resource(new PathResource(new File(path,"user.csv").getAbsolutePath()))
                .delimited()
                .names("id","name","age","addr")
                .targetType(User.class)
                .build();
    }

    // 定义itemWriter
    @Bean
    public MyBatisBatchItemWriter<User> csvToDbItemWriter(){
        return new MyBatisBatchItemWriterBuilder<User>()
                .sqlSessionFactory(sqlSessionFactory)
                .statementId("com.example.springbatch.mapper.UserMapper.saveUserTemp")
                .build();
    }

    // 定义Step
    @Bean
    public Step csvToDbStep(){
        return stepBuilderFactory.get("csvToDbStep")
                .<User,User>chunk(10000)
                .reader(csvToDbItemReader())
//                .writer(userService::saveUserTempBatch) // 使用 UserService 执行批量插入
                .writer(csvToDbItemWriter())
                .taskExecutor(new SimpleAsyncTaskExecutor())
                .build();
    }

    // 定义Job
    @Bean
    public Job csvToDbJob(){
        return jobBuilderFactory.get("csvToDbJob")
                .start(csvToDbStep())
                .incrementer(new RunIdIncrementer())
                .listener(new CsvToDbJobListener())
                .build();
    }
}

模拟另一个场景,从数据库中A表中读取数据,同步到数据库表B生成数据。使用异步分区处理方式来生成50w条数据,

package com.example.springbatch.job.config;

import com.example.springbatch.entity.User;
import com.example.springbatch.job.listener.CsvToDbJobListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.batch.MyBatisBatchItemWriter;
import org.mybatis.spring.batch.MyBatisCursorItemReader;
import org.mybatis.spring.batch.MyBatisPagingItemReader;
import org.mybatis.spring.batch.builder.MyBatisBatchItemWriterBuilder;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author GoryLee
 * @Date 2024/9/18
 */
@Configuration
@Slf4j
public class DbToDbJobConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    // 从步骤
    @Bean
    @StepScope
    public MyBatisPagingItemReader<User> dbToDbItemReader(
            @Value("#{stepExecutionContext[from]}") Integer from,
            @Value("#{stepExecutionContext[to]}") Integer to,
            @Value("#{stepExecutionContext[range]}") Integer range){
        log.info("------MyBatisPagingItemReader开始----from:"+from+"----to:"+to+"-----每片数量:"+range);
        MyBatisPagingItemReader<User> itemReader = new MyBatisPagingItemReader<>();
        itemReader.setSqlSessionFactory(sqlSessionFactory);
        itemReader.setPageSize(1000);
        itemReader.setQueryId("com.example.springbatch.mapper.UserMapper.selectUserTempList");
        Map<String,Object> map = new HashMap<>();
        map.put("from",from);
        map.put("to",to);
        itemReader.setParameterValues(map);
        return itemReader;
    }

    @Bean
    public MyBatisBatchItemWriter<User> dbToDbItemWriter(){
        return new MyBatisBatchItemWriterBuilder<User>()
                .sqlSessionFactory(sqlSessionFactory)
                .statementId("com.example.springbatch.mapper.UserMapper.saveUser")
                .build();
    }

    // 定义Step
    @Bean
    public Step workerStep(){
        return stepBuilderFactory.get("dbToDb_workerStep")
                .<User,User>chunk(10000)
                .reader(dbToDbItemReader(null,null,null))
                .writer(dbToDbItemWriter())
                .taskExecutor(new SimpleAsyncTaskExecutor())
                .build();
    }

    // 分区器
    @Bean
    public Partitioner dbToDbPartitioner(){
        return new DbToDbPartitioner();
    }

    // 分区处理器
    @Bean
    public PartitionHandler dbToDbPartitionerHandler(){
        TaskExecutorPartitionHandler handler = new TaskExecutorPartitionHandler();
        handler.setGridSize(50);
        handler.setStep(workerStep());
        handler.setTaskExecutor(new SimpleAsyncTaskExecutor());
        try {
            handler.afterPropertiesSet();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return handler;
    }

    // 主步骤
    @Bean
    public Step masterStep(){
        return stepBuilderFactory.get("dbToDb_masterStep")
                .partitioner(workerStep().getName(),dbToDbPartitioner())
                .partitionHandler(dbToDbPartitionerHandler())
                .build();
    }

    // 作业
    @Bean
    public Job dbToDbJob(){
        return jobBuilderFactory.get("dbToDbJob")
                .start(masterStep())
                .incrementer(new RunIdIncrementer())
                .build();
    }
}

分区器

package com.example.springbatch.job.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.item.ExecutionContext;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description 分区器设置,把从步骤的from,to,和range 3个设置到从步骤上下文中
 * @Author GoryLee
 * @Date 2024/9/18
 */
@Slf4j
public class DbToDbPartitioner implements Partitioner {
    @Override
    public Map<String, ExecutionContext> partition(int girdSize) {
        String text = "---DbToDbPartitioner--第%s分区-----开始:%s-----结束:%s ---- 数据量:%s------";
        Map<String,ExecutionContext> map = new HashMap<>();
        int from = 1;
        int to = 10000;
        int range = 10000;
        for (int i = 0; i < girdSize; i++) {
            log.info(String.format(text,i,from,to,(to-from+1)));
            ExecutionContext executionContext = new ExecutionContext();
            executionContext.putInt("from",from);
            executionContext.putInt("to",to);
            executionContext.putInt("range",range);
            to += range;
            from +=range;

            map.put("partitioner_"+i,executionContext);

        }
        return map;
    }
}
2.5 使用restful的方式启动批处理作业
package com.example.springbatch.controller;

import com.example.springbatch.mapper.UserMapper;
import example.common.model.Result;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.*;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.URISyntaxException;
import java.util.Date;

/**
 * @Description
 * @Author GoryLee
 * @Date 2024/9/14
 */
@RestController
@RequestMapping("/job")
@Slf4j
public class JobController {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    @Qualifier("csvToDbJob")
    private Job csvToDbJob;
    @Autowired
    @Qualifier("dbToDbJob")
    private Job dbToDbJob;

    @Autowired
    private JobExplorer jobExplorer;



    @GetMapping("/csvToDb")
    public Result<BatchStatus> csvToDb() throws Exception{
        userMapper.truncateAllTemp();
        JobParameters jobParameters = new JobParametersBuilder(new JobParameters(), jobExplorer)
                .addLong("time", System.currentTimeMillis())
                .getNextJobParameters(csvToDbJob)
                .toJobParameters();

        JobExecution run = jobLauncher.run(csvToDbJob, jobParameters);
        return Result.createSuccess(run.getStatus());
    }


    @GetMapping("/dbToDb")
    public Result<BatchStatus> dbToDb() throws Exception{
        userMapper.truncateAll();
        JobParameters jobParameters = new JobParametersBuilder(new JobParameters(), jobExplorer)
                .addLong("time", System.currentTimeMillis())
                .getNextJobParameters(dbToDbJob)
                .toJobParameters();

        JobExecution run = jobLauncher.run(dbToDbJob, jobParameters);
        return Result.createSuccess(run.getStatus());
    }
}

2.6 使用xxljob调度的方式启动批处理作业
package com.example.springbatch.job;

import com.example.springbatch.service.UserService;
import com.xxl.job.core.handler.annotation.XxlJob;
import example.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

/**
 * @Description
 * @Author GoryLee
 * @Date 2023/6/27
 */
@Component
@Slf4j
public class DemoJob {

    @Autowired
    private UserService userService;

    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    @Qualifier("dbToDbJob")
    private Job dbToDbJob;

    @Autowired
    private JobExplorer jobExplorer;

    @XxlJob("dbToDbJobHandler")
    public void dbToDbJobHandler() throws Exception {
        log.info(">>>>>>>>>> BEAN模式(类形式) 开始 >>>>>>>>>>>>>>>");
        userService.truncateAll();
        JobParameters jobParameters = new JobParametersBuilder(new JobParameters(), jobExplorer)
                .addLong("time", System.currentTimeMillis())
                .getNextJobParameters(dbToDbJob)
                .toJobParameters();

        JobExecution run = jobLauncher.run(dbToDbJob, jobParameters);
        log.info(">>>>>>>>>> 作业调度完成,状态:"+run.getStatus()+" >>>>>>>>>>>>>>>");
        log.info(">>>>>>>>>> BEAN模式(类形式) 成功 >>>>>>>>>>>>>>>");
    }
}
3. 总结

我这里只是简单的描述了整合使用,很多springbatch的概念是没有说清楚的,其次文章中很多代码为什么这么用我是没有说明的,所以想要更深入了解学习springbatch,还是到官方文档阅读学习:https://docs.spring.io/spring-batch/docs/4.3.10/reference/html/

另外文章中的两个简单场景,有完整代码的demo,如有需要运行,就自己去下载:https://github.com/gorylee/learnDemo/tree/master/springbatchDemo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2149902.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++11右值引用和移动语义

一.左值引用和右值引用 什么是左值引用&#xff0c;什么是右值引用 左值是一个表示数据的表达式&#xff08;变量名解引用的指针&#xff09;&#xff0c;我们可以获取到它的地址&#xff0c;可以对它赋值&#xff0c;左值可以出现在符号的左边。使用const修饰后&#xff0c;…

python检测keycloak证书连接报错问题

最近一直被keycloak的证书问题困扰了很久&#xff0c;老是提示ssl安全连接&#xff0c;由于不会java,只好硬着头皮用python测试。 我这里的证书是自己签注的证书&#xff0c;导入系统的是CA根证书。 from keycloak import KeycloakOpenID# 1. 配置 Keycloak 客户端 keycloak_o…

电子画册3D翻页电子版是如何制作

​随着科技的发展&#xff0c;传统的纸质画册逐渐被电子画册所取代。电子画册3D翻页电子版以其独特的交互方式和丰富的视觉体验&#xff0c;受到了越来越多人的喜爱。让我来教你怎么制作吧。 1.要制作电子杂志,首先需要选择一款适合自己的软件。比如FLBOOK在线制作电子杂志平台…

信息收集常用指令

目的 本文主要是记录一些在信息搜集时&#xff0c;常用的提高搜索效率的命令。 后续会继续记录一些用到的更多指令和方法&#xff0c;慢慢更新。 1、inurl “inurl:xxx”是指查找url中包含xxx的网页。 URL&#xff1a;统一资源定位符。统一资源定位系统。可以说包含域名&am…

ThreaLocal

1.概述 ThreadLoca称线程局部变量&#xff0c;用于在线程中保存数据&#xff0c;保存的数据仅属于当前线程(即对其他线程而言&#xff0c;该变量是当前线程独有的变量) threadLocal利用Thread中的ThreadLocalMap来进行数据存储 2.常用方法 存储数据至当前线程ThreadLocalMap中…

无监督神经组合优化的扩散模型框架

文章目录 Abstract1. Introduction2. Problem Description2.1 无监督神经组合优化3. Neural Probabilistic Optimization Objective for Approximate Likelihood Models3.1 具有联合变分上界的训练扩散模型Abstract 从离散集合的不可处理分布中进行采样,而不依赖相应的训练数据…

OpenAI o1解决了Quiet-STaR的挑战吗?(下)

随着OpenAI o1近期的发布&#xff0c;业界讨论o1关联论文最多之一可能是早前这篇斯坦福大学和Notbad AI Inc的研究人员开发的Quiet-STaR&#xff0c;即让AI学会先安静的“思考”再“说话” &#xff0c;回想自己一年前对于这一领域的思考和探索&#xff0c;当初也将这篇论文进行…

初学者蒙语学习,使用什么翻译软件学习更快?

为了加快蒙古语的学习&#xff0c;初学者应该从基础语法和词汇入手&#xff0c;利用语言学习应用进行系统学习&#xff0c;并通过音频和视频材料提高听力。语言交换和参加课程可以提供实践机会&#xff0c;而使用闪卡和文化沉浸有助于记忆词汇和理解语言背景。定期复习和设定学…

聊天组件 Vue3-beautiful-chat 插槽

前言 Vue3-beautiful-chat 组件有四个插槽可以定制 一、user-avatar(头像) 首先是头像插槽,我们可以直接在 <beautiful-chat></beautiful-chat> 中间使用; 作用: 我们可以在用户头像上添加自定义样式,比如添加节日边框、可以使用首字母作为头像。。。 …

小阿轩yx-通过state模块定义主机状态

小阿轩yx-通过state模块定义主机状态 前言 前面学习了远程执行模块&#xff0c;这些模块的执行类似语段 shell 脚本&#xff0c;每次执行都会触发一次相同的功能&#xff0c;在大量的 minion 上运行远程命令当然是重要的&#xff0c;但是对于 minion 的环境控制&#xff0c;使…

Python 二级考试

易错点 定义学生关系模式如下&#xff1a;Student &#xff08;S#&#xff0c; Sn&#xff0c; Ssex&#xff0c;class&#xff0c;monitorS#&#xff09;&#xff08;其属性分别为学号、学生名、性别、班级和班长学号&#xff09; 在关系模式中&#xff0c;如果Y -> X&…

超详细!百分百安装成功pytorch,建议收藏

文章目录 一、Anaconda安装1.1下载anaconda1.2配置Anaconda环境1.3验证anaconda是否安装成功 二、查看电脑显卡三、更新显卡驱动3.1下载驱动3.2、查看显卡驱动版本 四、cuda安装4.1CUDA下载4.2CUDA环境配置4.3验证CUDA是否安装成功 五、安装pytorch4.1下载pytorch5.2验证pytorc…

计算机专业的就业方向

计算机专业的就业方向 亲爱的新生们&#xff0c;欢迎你们踏上计算机科学的旅程&#xff01;作为一名计算机专业的学生&#xff0c;你们即将进入一个充满无限可能的领域。今天&#xff0c;我将为大家介绍计算机专业的一些主要就业方向&#xff0c;帮助你们了解未来的职业选择。…

备忘录应用哪些值得推荐?优秀的桌面备忘录下载

在我们的日常生活和工作中&#xff0c;备忘录是一款常用的记录软件&#xff0c;它为我们提供了极大的便利&#xff0c;让我们可以随时记录下重要的信息、灵感和待办事项。然而&#xff0c;如今网上的备忘录软件琳琅满目&#xff0c;究竟哪一款才是真正优秀的呢&#xff1f; 在…

分步指南:如何使用 ChatGPT 撰写文献综述

撰写文献综述对于研究人员和学生来说,往往是一项既耗时又复杂的任务。这一过程不仅要求对所选主题的现有研究进行全面的了解和掌握,还需要学术严谨性。然而,随着像 ChatGPT 这样的高级语言模型的广泛应用,撰写文献综述的过程变得更加高效和简化。通过合理利用 ChatGPT,研究…

分享三款简单好用的文档翻译软件

在平时的工作学习中免不了会碰上需要翻译文件的时候&#xff0c;给大家分享三款简单好用的翻译软件&#xff0c;可以直接翻译整篇的文档&#xff0c;翻译速度快&#xff0c;准确率高&#xff0c;可以大大提高效率。 1.谷歌翻译 这个翻译软件支持在线翻译&#xff0c;也可以翻…

华为 HCIP-Datacom H12-821 题库 (25)

&#x1f423;博客最下方微信公众号回复题库,领取题库和教学资源 &#x1f424;诚挚欢迎IT交流有兴趣的公众号回复交流群 &#x1f998;公众号会持续更新网络小知识&#x1f63c; 1.以下哪些事件会导致 IS-IS 产生一个新的 LSP? A、邻接 Up 或Down B、引入的 IP 路由发送变…

康佳集团的多元化战略:创新还是负担?

2023年&#xff0c;康佳集团豪赌“一轴两轮三驱动”战略&#xff0c;企图以消费电子和半导体为马&#xff0c;来驱动业绩的快车&#xff0c;但2024年的半年报如同一盆冷水&#xff0c;让所有期望化为泡影。 财报显示&#xff0c;康佳上半年营业总收入只有54.13亿元&#xff0c…

传输大咖44 | 云计算企业大数据迁移如何更安全高效?

在云计算时代&#xff0c;数据已成为企业最宝贵的资产之一。对于依赖云服务的企业和组织来说&#xff0c;大数据迁移是实现业务扩展和优化的关键步骤。然而&#xff0c;这一过程并非没有挑战。传统的文件传输方式在安全性、稳定性和速度上往往无法满足云计算企业的需求。本文将…

ORCA-3D避障代码和原理解析

二维ORCA原理参考&#xff1a; https://zhuanlan.zhihu.com/p/669426124 ORCA原理图解代码解释 1. 找到避障速度增量 u 碰撞处理分为三种情况&#xff1a; &#xff08;1&#xff09;没有发生碰撞&#xff0c;且相对速度落在小圆里 &#xff08;2&#xff09;没有发生碰撞&a…