job源码分析_new jobconf-程序员宅基地

  1. /** 
  2.  * Licensed to the Apache Software Foundation (ASF) under one 
  3.  * or more contributor license agreements.  See the NOTICE file 
  4.  * distributed with this work for additional information 
  5.  * regarding copyright ownership.  The ASF licenses this file 
  6.  * to you under the Apache License, Version 2.0 (the 
  7.  * "License"); you may not use this file except in compliance 
  8.  * with the License.  You may obtain a copy of the License at 
  9.  * 
  10.  *     http://www.apache.org/licenses/LICENSE-2.0 
  11.  * 
  12.  * Unless required by applicable law or agreed to in writing, software 
  13.  * distributed under the License is distributed on an "AS IS" BASIS, 
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  15.  * See the License for the specific language governing permissions and 
  16.  * limitations under the License. 
  17.  */  
  18.   
  19. package org.apache.hadoop.mapreduce;  
  20.   
  21. import java.io.IOException;  
  22. import java.security.PrivilegedExceptionAction;  
  23.   
  24. import org.apache.hadoop.conf.Configuration;  
  25. import org.apache.hadoop.fs.Path;  
  26. import org.apache.hadoop.io.RawComparator;  
  27. import org.apache.hadoop.mapreduce.TaskAttemptID;  
  28. import org.apache.hadoop.mapred.JobClient;  
  29. import org.apache.hadoop.mapred.JobConf;  
  30. import org.apache.hadoop.mapred.RunningJob;  
  31. import org.apache.hadoop.mapred.TaskCompletionEvent;  
  32.   
  33. /** 
  34.  * The job submitter's view of the Job. It allows the user to configure the 
  35.  * job, submit it, control its execution, and query the state. The set methods 
  36.  * only work until the job is submitted, afterwards they will throw an  
  37.  * IllegalStateException. 
  38.  * job 提交者看到的job的视图。它允许用户配置job,提交job,控制job的执行,并且查询他的状态 
  39.  * set方法只有在job提交的时候才会工作 
  40.  */  
  41. public class Job extends JobContext {    
  42.   public static enum JobState {DEFINE, RUNNING};//job的状态,有定义好的和正在运行  
  43.   private JobState state = JobState.DEFINE;  
  44.   private JobClient jobClient;  
  45.   private RunningJob info;  
  46.   
  47.   /** 
  48.    * Creates a new {@link Job} 
  49.    * A Job will be created with a generic {@link Configuration}. 
  50.    *创建一个新的job,用通用的configuration 
  51.    * @return the {@link Job} 
  52.    * @throws IOException 
  53.    */  
  54.   public static Job getInstance() throws IOException {  
  55.     // create with a null Cluster  
  56.     return getInstance(new Configuration());  
  57.   }  
  58.   
  59.   /** 
  60.    * Creates a new {@link Job} with a given {@link Configuration}. 
  61.    * The <code>Job</code> makes a copy of the <code>Configuration</code> so 
  62.    * that any necessary internal modifications do not reflect on the incoming 
  63.    * parameter. 
  64.    *使用给定的configuration创建job 
  65.    *这里对configuration进行了备份,如此,任何必要的对configuration内部修改,都不会影响传进来的conf参数 
  66.    * @param conf the {@link Configuration} 
  67.    * @return the {@link Job} 
  68.    * @throws IOException 
  69.    */  
  70.   public static Job getInstance(Configuration conf) throws IOException {  
  71.     // create with a null Cluster 没有任何集群的创建  
  72.     JobConf jobConf = new JobConf(conf);  
  73.     return new Job(jobConf);  
  74.   }  
  75.   
  76.   /** 
  77.    * Creates a new {@link Job} with a given {@link Configuration} 
  78.    * and a given jobName. 
  79.    *用给定的conf和jobname 
  80.    * The <code>Job</code> makes a copy of the <code>Configuration</code> so 
  81.    * that any necessary internal modifications do not reflect on the incoming 
  82.    * parameter. 
  83.    * 
  84.    * @param conf the {@link Configuration} 
  85.    * @param jobName the job instance's name 
  86.    * @return the {@link Job} 
  87.    * @throws IOException 
  88.    */  
  89.   public static Job getInstance(Configuration conf, String jobName)  
  90.            throws IOException {  
  91.     // create with a null Cluster  
  92.     Job result = getInstance(conf);  
  93.     result.setJobName(jobName);  
  94.     return result;  
  95.   }  
  96.   
  97.   public Job() throws IOException {  
  98.     this(new Configuration());  
  99.   }  
  100.   
  101.   public Job(Configuration conf) throws IOException {  
  102.     super(conf, null);  
  103.   }  
  104.   
  105.   public Job(Configuration conf, String jobName) throws IOException {  
  106.     this(conf);  
  107.     setJobName(jobName);  
  108.   }  
  109.   
  110.   JobClient getJobClient() {  
  111.     return jobClient;  
  112.   }  
  113.     
  114.   //确保job的状态  
  115.   private void ensureState(JobState state) throws IllegalStateException {  
  116.     if (state != this.state) {  
  117.       throw new IllegalStateException("Job in state "+ this.state +   
  118.                                       " instead of " + state);  
  119.     }  
  120.   
  121.     if (state == JobState.RUNNING && jobClient == null) {  
  122.       throw new IllegalStateException("Job in state " + JobState.RUNNING +   
  123.                                       " however jobClient is not initialized!");  
  124.     }  
  125.   }  
  126.   
  127.   /** 
  128.    * Set the number of reduce tasks for the job. 
  129.    * 设置reducer的个数 常用 
  130.    * @param tasks the number of reduce tasks 
  131.    * @throws IllegalStateException if the job is submitted 
  132.    */  
  133.   public void setNumReduceTasks(int tasks) throws IllegalStateException {  
  134.     ensureState(JobState.DEFINE);  
  135.     conf.setNumReduceTasks(tasks);  
  136.   }  
  137.   
  138.   /** 
  139.    * Set the current working directory for the default file system. 
  140.    * 为默认文件系统 设置当前工作目录 
  141.    * @param dir the new current working directory. 
  142.    * @throws IllegalStateException if the job is submitted 
  143.    */  
  144.   public void setWorkingDirectory(Path dir) throws IOException {  
  145.     ensureState(JobState.DEFINE);  
  146.     conf.setWorkingDirectory(dir);  
  147.   }  
  148.   
  149.   /** 
  150.    * Set the {@link InputFormat} for the job. 
  151.    * @param cls the <code>InputFormat</code> to use 
  152.    * @throws IllegalStateException if the job is submitted 
  153.    */  
  154.   public void setInputFormatClass(Class<? extends InputFormat> cls  
  155.                                   ) throws IllegalStateException {  
  156.     ensureState(JobState.DEFINE);  
  157.     conf.setClass(INPUT_FORMAT_CLASS_ATTR, cls, InputFormat.class);  
  158.   }  
  159.   
  160.   /** 
  161.    * Set the {@link OutputFormat} for the job. 
  162.    * @param cls the <code>OutputFormat</code> to use 
  163.    * @throws IllegalStateException if the job is submitted 
  164.    */  
  165.   public void setOutputFormatClass(Class<? extends OutputFormat> cls  
  166.                                    ) throws IllegalStateException {  
  167.     ensureState(JobState.DEFINE);  
  168.     conf.setClass(OUTPUT_FORMAT_CLASS_ATTR, cls, OutputFormat.class);  
  169.   }  
  170.   
  171.   /** 
  172.    * Set the {@link Mapper} for the job. 
  173.    * @param cls the <code>Mapper</code> to use 
  174.    * @throws IllegalStateException if the job is submitted 
  175.    */  
  176.   public void setMapperClass(Class<? extends Mapper> cls  
  177.                              ) throws IllegalStateException {  
  178.     ensureState(JobState.DEFINE);  
  179.     conf.setClass(MAP_CLASS_ATTR, cls, Mapper.class);  
  180.   }  
  181.   
  182.   /** 
  183.    * Set the Jar by finding where a given class came from. 
  184.    * 设置jar包,hadoop根据给定的class来寻找他的jar包 
  185.    * @param cls the example class 
  186.    */  
  187.   public void setJarByClass(Class<?> cls) {  
  188.     conf.setJarByClass(cls);  
  189.   }  
  190.     
  191.   /** 
  192.    * Get the pathname of the job's jar. 
  193.    * @return the pathname 
  194.    */  
  195.   public String getJar() {  
  196.     return conf.getJar();  
  197.   }  
  198.   
  199.   /** 
  200.    * Set the combiner class for the job. 
  201.    * @param cls the combiner to use 
  202.    * @throws IllegalStateException if the job is submitted 
  203.    */  
  204.   public void setCombinerClass(Class<? extends Reducer> cls  
  205.                                ) throws IllegalStateException {  
  206.     ensureState(JobState.DEFINE);  
  207.     conf.setClass(COMBINE_CLASS_ATTR, cls, Reducer.class);  
  208.   }  
  209.   
  210.   /** 
  211.    * Set the {@link Reducer} for the job. 
  212.    * @param cls the <code>Reducer</code> to use 
  213.    * @throws IllegalStateException if the job is submitted 
  214.    */  
  215.   public void setReducerClass(Class<? extends Reducer> cls  
  216.                               ) throws IllegalStateException {  
  217.     ensureState(JobState.DEFINE);  
  218.     conf.setClass(REDUCE_CLASS_ATTR, cls, Reducer.class);  
  219.   }  
  220.   
  221.   /** 
  222.    * Set the {@link Partitioner} for the job. 
  223.    * @param cls the <code>Partitioner</code> to use 
  224.    * @throws IllegalStateException if the job is submitted 
  225.    */  
  226.   public void setPartitionerClass(Class<? extends Partitioner> cls  
  227.                                   ) throws IllegalStateException {  
  228.     ensureState(JobState.DEFINE);  
  229.     conf.setClass(PARTITIONER_CLASS_ATTR, cls, Partitioner.class);  
  230.   }  
  231.   
  232.   /** 
  233.    * Set the key class for the map output data. This allows the user to 
  234.    * specify the map output key class to be different than the final output 
  235.    * value class. 
  236.    *  
  237.    * @param theClass the map output key class. 
  238.    * @throws IllegalStateException if the job is submitted 
  239.    */  
  240.   public void setMapOutputKeyClass(Class<?> theClass  
  241.                                    ) throws IllegalStateException {  
  242.     ensureState(JobState.DEFINE);  
  243.     conf.setMapOutputKeyClass(theClass);  
  244.   }  
  245.   
  246.   /** 
  247.    * Set the value class for the map output data. This allows the user to 
  248.    * specify the map output value class to be different than the final output 
  249.    * value class. 
  250.    *  
  251.    * @param theClass the map output value class. 
  252.    * @throws IllegalStateException if the job is submitted 
  253.    */  
  254.   public void setMapOutputValueClass(Class<?> theClass  
  255.                                      ) throws IllegalStateException {  
  256.     ensureState(JobState.DEFINE);  
  257.     conf.setMapOutputValueClass(theClass);  
  258.   }  
  259.   
  260.   /** 
  261.    * Set the key class for the job output data. 
  262.    *  
  263.    * @param theClass the key class for the job output data. 
  264.    * @throws IllegalStateException if the job is submitted 
  265.    */  
  266.   public void setOutputKeyClass(Class<?> theClass  
  267.                                 ) throws IllegalStateException {  
  268.     ensureState(JobState.DEFINE);  
  269.     conf.setOutputKeyClass(theClass);  
  270.   }  
  271.   
  272.   /** 
  273.    * Set the value class for job outputs. 
  274.    *  
  275.    * @param theClass the value class for job outputs. 
  276.    * @throws IllegalStateException if the job is submitted 
  277.    */  
  278.   public void setOutputValueClass(Class<?> theClass  
  279.                                   ) throws IllegalStateException {  
  280.     ensureState(JobState.DEFINE);  
  281.     conf.setOutputValueClass(theClass);  
  282.   }  
  283.   
  284.   /** 
  285.    * Define the comparator that controls how the keys are sorted before they 
  286.    * are passed to the {@link Reducer}. 
  287.    * @param cls the raw comparator 
  288.    * @throws IllegalStateException if the job is submitted 
  289.    */  
  290.   public void setSortComparatorClass(Class<? extends RawComparator> cls  
  291.                                      ) throws IllegalStateException {  
  292.     ensureState(JobState.DEFINE);  
  293.     conf.setOutputKeyComparatorClass(cls);  
  294.   }  
  295.   
  296.   /** 
  297.    * Define the comparator that controls which keys are grouped together 
  298.    * for a single call to  
  299.    * {@link Reducer#reduce(Object, Iterable,  
  300.    *                       org.apache.hadoop.mapreduce.Reducer.Context)} 
  301.    * @param cls the raw comparator to use 
  302.    * @throws IllegalStateException if the job is submitted 
  303.    */  
  304.   public void setGroupingComparatorClass(Class<? extends RawComparator> cls  
  305.                                          ) throws IllegalStateException {  
  306.     ensureState(JobState.DEFINE);  
  307.     conf.setOutputValueGroupingComparator(cls);  
  308.   }  
  309.   
  310.   /** 
  311.    * Set the user-specified job name. 
  312.    *  
  313.    * @param name the job's new name. 
  314.    * @throws IllegalStateException if the job is submitted 
  315.    */  
  316.   public void setJobName(String name) throws IllegalStateException {  
  317.     ensureState(JobState.DEFINE);  
  318.     conf.setJobName(name);  
  319.   }  
  320.     
  321.   /** 
  322.    * Turn speculative execution on or off for this job.  
  323.    * 设置推测执行的开关 
  324.    * @param speculativeExecution <code>true</code> if speculative execution  
  325.    *                             should be turned on, else <code>false</code>. 
  326.    */  
  327.   public void setSpeculativeExecution(boolean speculativeExecution) {  
  328.     ensureState(JobState.DEFINE);  
  329.     conf.setSpeculativeExecution(speculativeExecution);  
  330.   }  
  331.   
  332.   /** 
  333.    * Turn speculative execution on or off for this job for map tasks.  
  334.    *  
  335.    * @param speculativeExecution <code>true</code> if speculative execution  
  336.    *                             should be turned on for map tasks, 
  337.    *                             else <code>false</code>. 
  338.    */  
  339.   public void setMapSpeculativeExecution(boolean speculativeExecution) {  
  340.     ensureState(JobState.DEFINE);  
  341.     conf.setMapSpeculativeExecution(speculativeExecution);  
  342.   }  
  343.   
  344.   /** 
  345.    * Turn speculative execution on or off for this job for reduce tasks.  
  346.    *  
  347.    * @param speculativeExecution <code>true</code> if speculative execution  
  348.    *                             should be turned on for reduce tasks, 
  349.    *                             else <code>false</code>. 
  350.    */  
  351.   public void setReduceSpeculativeExecution(boolean speculativeExecution) {  
  352.     ensureState(JobState.DEFINE);  
  353.     conf.setReduceSpeculativeExecution(speculativeExecution);  
  354.   }  
  355.   
  356.   /** 
  357.    * Get the URL where some job progress information will be displayed. 
  358.    * 得到 一些job 进度信息会展示的url地址 
  359.    * @return the URL where some job progress information will be displayed. 
  360.    */  
  361.   public String getTrackingURL() {  
  362.     ensureState(JobState.RUNNING);  
  363.     return info.getTrackingURL();  
  364.   }  
  365.   
  366.   /** 
  367.    * Get the <i>progress</i> of the job's setup, as a float between 0.0  
  368.    * and 1.0.  When the job setup is completed, the function returns 1.0. 
  369.    *  
  370.    * @return the progress of the job's setup. 
  371.    * @throws IOException 
  372.    */  
  373.   public float setupProgress() throws IOException {  
  374.     ensureState(JobState.RUNNING);  
  375.     return info.setupProgress();  
  376.   }  
  377.   
  378.   /** 
  379.    * Get the <i>progress</i> of the job's map-tasks, as a float between 0.0  
  380.    * and 1.0.  When all map tasks have completed, the function returns 1.0. 
  381.    *  
  382.    * @return the progress of the job's map-tasks. 
  383.    * @throws IOException 
  384.    */  
  385.   public float mapProgress() throws IOException {  
  386.     ensureState(JobState.RUNNING);  
  387.     return info.mapProgress();  
  388.   }  
  389.   
  390.   /** 
  391.    * Get the <i>progress</i> of the job's reduce-tasks, as a float between 0.0  
  392.    * and 1.0.  When all reduce tasks have completed, the function returns 1.0. 
  393.    *  
  394.    * @return the progress of the job's reduce-tasks. 
  395.    * @throws IOException 
  396.    */  
  397.   public float reduceProgress() throws IOException {  
  398.     ensureState(JobState.RUNNING);  
  399.     return info.reduceProgress();  
  400.   }  
  401.   
  402.   /** 
  403.    * Check if the job is finished or not.  
  404.    * This is a non-blocking call. 
  405.    *  
  406.    * @return <code>true</code> if the job is complete, else <code>false</code>. 
  407.    * @throws IOException 
  408.    */  
  409.   public boolean isComplete() throws IOException {  
  410.     ensureState(JobState.RUNNING);  
  411.     return info.isComplete();  
  412.   }  
  413.   
  414.   /** 
  415.    * Check if the job completed successfully.  
  416.    *  
  417.    * @return <code>true</code> if the job succeeded, else <code>false</code>. 
  418.    * @throws IOException 
  419.    */  
  420.   public boolean isSuccessful() throws IOException {  
  421.     ensureState(JobState.RUNNING);  
  422.     return info.isSuccessful();  
  423.   }  
  424.   
  425.   /** 
  426.    * Kill the running job.  Blocks until all job tasks have been 
  427.    * killed as well.  If the job is no longer running, it simply returns. 
  428.    * 杀掉正在运行的job 直到所有的job tasks都被杀掉之后 才会停止。 
  429.    * 如果job不再运行来 他就会返回 
  430.    * @throws IOException 
  431.    */  
  432.   public void killJob() throws IOException {  
  433.     ensureState(JobState.RUNNING);  
  434.     info.killJob();  
  435.   }  
  436.       
  437.   /** 
  438.    * Get events indicating completion (success/failure) of component tasks. 
  439.    *   
  440.    * @param startFrom index to start fetching events from 
  441.    * @return an array of {@link TaskCompletionEvent}s 
  442.    * @throws IOException 
  443.    */  
  444.   public TaskCompletionEvent[] getTaskCompletionEvents(int startFrom  
  445.                                                        ) throws IOException {  
  446.     ensureState(JobState.RUNNING);  
  447.     return info.getTaskCompletionEvents(startFrom);  
  448.   }  
  449.     
  450.   /** 
  451.    * Kill indicated task attempt. 
  452.    *  
  453.    * @param taskId the id of the task to be terminated. 
  454.    * @throws IOException 
  455.    */  
  456.   public void killTask(TaskAttemptID taskId) throws IOException {  
  457.     ensureState(JobState.RUNNING);  
  458.     info.killTask(org.apache.hadoop.mapred.TaskAttemptID.downgrade(taskId),   
  459.                   false);  
  460.   }  
  461.   
  462.   /** 
  463.    * Fail indicated task attempt. 
  464.    *  
  465.    * @param taskId the id of the task to be terminated. 
  466.    * @throws IOException 
  467.    */  
  468.   public void failTask(TaskAttemptID taskId) throws IOException {  
  469.     ensureState(JobState.RUNNING);  
  470.     info.killTask(org.apache.hadoop.mapred.TaskAttemptID.downgrade(taskId),   
  471.                   true);  
  472.   }  
  473.   
  474.   /** 
  475.    * Gets the counters for this job. 
  476.    *  
  477.    * @return the counters for this job. 
  478.    * @throws IOException 
  479.    */  
  480.   public Counters getCounters() throws IOException {  
  481.     ensureState(JobState.RUNNING);  
  482.     return new Counters(info.getCounters());  
  483.   }  
  484.   
  485.   private void ensureNotSet(String attr, String msg) throws IOException {  
  486.     if (conf.get(attr) != null) {  
  487.       throw new IOException(attr + " is incompatible with " + msg + " mode.");  
  488.     }      
  489.   }  
  490.     
  491.   /** 
  492.    * Sets the flag that will allow the JobTracker to cancel the HDFS delegation 
  493.    * tokens upon job completion. Defaults to true. 
  494.    */  
  495.   public void setCancelDelegationTokenUponJobCompletion(boolean value) {  
  496.     ensureState(JobState.DEFINE);  
  497.     conf.setBoolean(JOB_CANCEL_DELEGATION_TOKEN, value);  
  498.   }  
  499.   
  500.   /** 
  501.    * Default to the new APIs unless they are explicitly set or the old mapper or 
  502.    * reduce attributes are used. 
  503.    * @throws IOException if the configuration is inconsistant 
  504.    */  
  505.   private void setUseNewAPI() throws IOException {  
  506.     int numReduces = conf.getNumReduceTasks();  
  507.     String oldMapperClass = "mapred.mapper.class";  
  508.     String oldReduceClass = "mapred.reducer.class";  
  509.     conf.setBooleanIfUnset("mapred.mapper.new-api",  
  510.                            conf.get(oldMapperClass) == null);  
  511.     if (conf.getUseNewMapper()) {  
  512.       String mode = "new map API";  
  513.       ensureNotSet("mapred.input.format.class", mode);  
  514.       ensureNotSet(oldMapperClass, mode);  
  515.       if (numReduces != 0) {  
  516.         ensureNotSet("mapred.partitioner.class", mode);  
  517.        } else {  
  518.         ensureNotSet("mapred.output.format.class", mode);  
  519.       }        
  520.     } else {  
  521.       String mode = "map compatability";  
  522.       ensureNotSet(JobContext.INPUT_FORMAT_CLASS_ATTR, mode);  
  523.       ensureNotSet(JobContext.MAP_CLASS_ATTR, mode);  
  524.       if (numReduces != 0) {  
  525.         ensureNotSet(JobContext.PARTITIONER_CLASS_ATTR, mode);  
  526.        } else {  
  527.         ensureNotSet(JobContext.OUTPUT_FORMAT_CLASS_ATTR, mode);  
  528.       }  
  529.     }  
  530.     if (numReduces != 0) {  
  531.       conf.setBooleanIfUnset("mapred.reducer.new-api",  
  532.                              conf.get(oldReduceClass) == null);  
  533.       if (conf.getUseNewReducer()) {  
  534.         String mode = "new reduce API";  
  535.         ensureNotSet("mapred.output.format.class", mode);  
  536.         ensureNotSet(oldReduceClass, mode);     
  537.       } else {  
  538.         String mode = "reduce compatability";  
  539.         ensureNotSet(JobContext.OUTPUT_FORMAT_CLASS_ATTR, mode);  
  540.         ensureNotSet(JobContext.REDUCE_CLASS_ATTR, mode);     
  541.       }  
  542.     }     
  543.   }  
  544.   
  545.   /** 
  546.    * Submit the job to the cluster and return immediately. 
  547.    * 提交job到集群上面 并且立刻返回 
  548.    * @throws IOException 
  549.    */  
  550.   public void submit() throws IOException, InterruptedException,   
  551.                               ClassNotFoundException {  
  552.     ensureState(JobState.DEFINE);  
  553.     setUseNewAPI();  
  554.       
  555.     // Connect to the JobTracker and submit the job  
  556.     //连接到jobtracker 并且提交作业  
  557.     connect();  
  558.     info = jobClient.submitJobInternal(conf);//这里才真正的提交作业  
  559.     super.setJobID(info.getID());  
  560.     state = JobState.RUNNING;  
  561.    }  
  562.     
  563.   /** 
  564.    * Open a connection to the JobTracker 
  565.    * 打开到jobtracker的连接 
  566.    * @throws IOException 
  567.    * @throws InterruptedException  
  568.    */  
  569.   private void connect() throws IOException, InterruptedException {  
  570.     ugi.doAs(new PrivilegedExceptionAction<Object>() {  
  571.       public Object run() throws IOException {  
  572.         jobClient = new JobClient((JobConf) getConfiguration());      
  573.         return null;  
  574.       }  
  575.     });  
  576.   }  
  577.     
  578.   /** 
  579.    * Submit the job to the cluster and wait for it to finish. 
  580.    * @param verbose print the progress to the user 
  581.    * @return true if the job succeeded 
  582.    * @throws IOException thrown if the communication with the  
  583.    *         <code>JobTracker</code> is lost 
  584.    */  
  585.   public boolean waitForCompletion(boolean verbose  
  586.                                    ) throws IOException, InterruptedException,  
  587.                                             ClassNotFoundException {  
  588.     if (state == JobState.DEFINE) {  
  589.       submit();  
  590.     }  
  591.     if (verbose) {  
  592.       jobClient.monitorAndPrintJob(conf, info);  
  593.     } else {  
  594.       info.waitForCompletion();  
  595.     }  
  596.     return isSuccessful();  
  597.   }  
  598.     
  599. }  
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jiaxinhong/article/details/82826232

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文