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

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签