<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>mx's blog - java</title><link href="https://x-wei.github.io/" rel="alternate"/><link href="https://x-wei.github.io/feeds/tag-java.atom.xml" rel="self"/><id>https://x-wei.github.io/</id><updated>2016-05-21T00:00:00+02:00</updated><entry><title>在java程序里使用weka进行机器学习</title><link href="https://x-wei.github.io/soft/java-use-weka.html" rel="alternate"/><published>2016-05-21T00:00:00+02:00</published><updated>2016-05-21T00:00:00+02:00</updated><author><name>mx</name></author><id>tag:x-wei.github.io,2016-05-21:/soft/java-use-weka.html</id><summary type="html">&lt;p&gt;之前一直用weka的GUI界面做机器学习的任务, 感觉这个软件虽然界面丑, 不过确实是快速开展机器学期的利器. 关于GUI的weka使用以后有时间再写. 今天这篇记录一下最近使用的java版本的weka …&lt;/p&gt;</summary><content type="html">&lt;p&gt;之前一直用weka的GUI界面做机器学习的任务, 感觉这个软件虽然界面丑, 不过确实是快速开展机器学期的利器. 关于GUI的weka使用以后有时间再写. 今天这篇记录一下最近使用的java版本的weka.   &lt;/p&gt;
&lt;h1 id="1-include-jars-into-project"&gt;1. Include jars into project&lt;/h1&gt;
&lt;p&gt;weka官网的下载链接里选择linux版本的weka压缩包即可, 下载以后找到weka.jar文件, 在工程里将其include一下就可以使用了(btw, 现在开始放弃eclipse, 进入IDEA的怀抱了...).   &lt;/p&gt;
&lt;p&gt;weka的文档在解压缩的文件里有, 另外在线文档在: &lt;a href="http://weka.sourceforge.net/doc.stable-3-8/"&gt;http://weka.sourceforge.net/doc.stable-3-8/&lt;/a&gt; &lt;/p&gt;
&lt;h3 id="about-libsvm"&gt;about libsvm...&lt;/h3&gt;
&lt;p&gt;关于libsvm需要有一点特别指出. weka自带的算法里是不包含libsvm的 (有个类似的SMO, 不过还是libsvm久经考验啊...), 需要使用weka的package manager安装. 打开package manager是在weka主界面的菜单里: &lt;br/&gt;
&lt;img alt="" class="img-responsive" src="../images/java-use-weka/pasted_image002.png"/&gt;&lt;br/&gt;
在package manager里搜索到libsvm安装即可. 然后(linux下)在主目录可以看到有个wekafiles文件夹, &lt;code&gt;wekafiles/packages/LibSVM/&lt;/code&gt;目录下就是libsvm的内容.   &lt;/p&gt;
&lt;p&gt;需要指出的一点是, 要使用libsvm的话, &lt;a href="http://stackoverflow.com/questions/30821926/solved-weka-api-libsvm-classpath-not-found"&gt;需要同时引用两个jar文件&lt;/a&gt;, 而且都叫libsvm.jar!!   &lt;/p&gt;
&lt;p&gt;这两个jar, 一个叫&lt;code&gt;LibSVM.jar&lt;/code&gt;, 在&lt;code&gt;wekafiles/packages/LibSVM/&lt;/code&gt;下, 另一个叫&lt;code&gt;libsvm.jar&lt;/code&gt;, 在&lt;code&gt;wekafiles/packages/LibSVM/lib/&lt;/code&gt;下...orz  &lt;/p&gt;
&lt;p&gt;如果只include第一个jar的话, 就会报错: "java.lang.Exception: libsvm classes not in CLASSPATH! ".   &lt;/p&gt;
&lt;h1 id="2-terminology_1"&gt;2. terminology&lt;/h1&gt;
&lt;p&gt;首先统一一下各种东西的叫法...  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Instances&lt;/code&gt;: 就是dataset, 比如training set或者test set, Instances实际上就是一个Instance的集合  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Instance&lt;/code&gt;: 就是一个数据点了  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Attribute&lt;/code&gt;: 一个数据点有一些attribute (别处一般叫做feature), 其中有一个attribute其实是label(可以为missing)  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Classifier&lt;/code&gt;: weka里的Classifer其实是也包含了regressor或者cluster... 后面都称之为model  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Evaluation&lt;/code&gt;: 给定一个model和一个dataset, 给出evaluation的数据, 类似GUI界面给出的那些内容  &lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="3"&gt;3. 在程序里构建数据&lt;/h1&gt;
&lt;p&gt;这也是为什么要在java里用weka的原因: 如果数据可以直接以csv或者arff文件的方式得到, 那么直接在GUI界面下就可以搞了...  &lt;/p&gt;
&lt;h3 id="attribute"&gt;新建Attribute&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://weka.sourceforge.net/doc.stable-3-8/weka/core/Attribute.html"&gt;http://weka.sourceforge.net/doc.stable-3-8/weka/core/Attribute.html&lt;/a&gt; &lt;br/&gt;
新建numeric的attribue只要简单的在构造函数里传入一个attribute的名字即可:   &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create numeric attributes "length" and "weight"   &lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"length"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;新建离散(normial)的attribue则需要一个list乘放所有可能的数值:   &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create list to hold nominal values "first", "second", "third"   &lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_nominal_values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;my_nominal_values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;my_nominal_values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"second"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;my_nominal_values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"third"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="c1"&gt;// Create nominal attribute "position"   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_nominal_values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="instancesdataset"&gt;新建Instances(dataset)&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://weka.sourceforge.net/doc.stable-3-8/weka/core/Instances.html"&gt;http://weka.sourceforge.net/doc.stable-3-8/weka/core/Instances.html&lt;/a&gt;&lt;br/&gt;
&lt;code&gt;Instances&lt;/code&gt;实际上就是一个&lt;code&gt;Instance&lt;/code&gt;的集合, Instances可以类比为pandas里面的DataFrame, 然后每个instance相当于一行. 另外&lt;code&gt;Instances&lt;/code&gt;比&lt;code&gt;Instance&lt;/code&gt;多的就是Attribute信息(类比为pandas里DataFrame的表头head).   &lt;/p&gt;
&lt;p&gt;&lt;code&gt;Instances&lt;/code&gt;的构造函数有两种, 一种是直接在arff文件里读取, 这个后面再说. 另一种构造函数是在java函数里构建Instance时用的, 它构造一个空的Instance集合, 构造函数提供dataset的名字, attribute的集合(arraylist)以及初始的capacity:   &lt;/p&gt;
&lt;p&gt;&lt;code&gt;Instances(String name, ArrayList&amp;lt;Attribute&amp;gt; attInfo, int capacity)&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;其中的第二个参数attInfo其实就相当于是表头信息了, 它是一个Attribute的ArrayList.   &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ArrayList&amp;lt;Attribute&amp;gt; atts = new ArrayList&amp;lt;Attribute&amp;gt;();  &lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;atts.add(length);  &lt;/span&gt;
&lt;span class="code-line"&gt;atts.add(weight);  &lt;/span&gt;
&lt;span class="code-line"&gt;atts.add(position);  &lt;/span&gt;
&lt;span class="code-line"&gt;Instances adataset = new Instances("aDataSet", atts, 10);&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(上面代码里的&lt;code&gt;length&lt;/code&gt;, &lt;code&gt;weight&lt;/code&gt; 和&lt;code&gt;position&lt;/code&gt;都是前面声明的Attribute对象)  &lt;/p&gt;
&lt;p&gt;Instances还可以指定哪一列对应的是class label (单个Instance则不能 — 因为单个Instance并没有表头信息attInfo):   &lt;/p&gt;
&lt;p&gt;&lt;code&gt;void setClassIndex(int classIndex)&lt;/code&gt; &lt;/p&gt;
&lt;h3 id="instance"&gt;新建Instance&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://weka.sourceforge.net/doc.stable-3-8/weka/core/Instance.html"&gt;http://weka.sourceforge.net/doc.stable-3-8/weka/core/Instance.html&lt;/a&gt;&lt;br/&gt;
&lt;code&gt;Instance&lt;/code&gt;是一个接口而不是一个类, 一半常用的是&lt;code&gt;DenseInstance&lt;/code&gt;类(它又继承自&lt;code&gt;AbstractInstance&lt;/code&gt;抽象类)   &lt;/p&gt;
&lt;p&gt;这里有一个坑: 一定要指定Instance所属的DataSet(既它属于哪一个Instances对象)再使用setValue函数, 否则在调用setValue的时候可能会有问题!!!   &lt;/p&gt;
&lt;p&gt;&lt;code&gt;void setDataset(Instances instances)&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;构造函数里只需要提供这个instance的attribute数量即可. 然后使用&lt;code&gt;setValue&lt;/code&gt;函数可以给每个attribue指定数值. setValue函数的第一个参数接收一个Attribue对象, 第二个参数就是这个attribue的数值(double或者string).   &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create empty instance with three attribute values   &lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;Instance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DenseInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setDataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;adataset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// before calling setValue, should first set the Dataset!``  &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="c1"&gt;// Set instance's values for the attributes "length", "weight", and "position"  &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="4-model_1"&gt;4. 在程序里训练model&lt;/h1&gt;
&lt;p&gt;这里只做classification的例子好了. &lt;br/&gt;
&lt;a href="http://weka.sourceforge.net/doc.stable-3-8/weka/classifiers/Classifier.html"&gt;http://weka.sourceforge.net/doc.stable-3-8/weka/classifiers/Classifier.html&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Classifier是一个Interface, 可以在文档里看到有很多类都实现了这个interface, 主要是三个常用的函数:   &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;void buildClassifier(Instances data)&lt;/code&gt; : 用data数据进行训练  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;double   classifyInstance(Instance instance)&lt;/code&gt; : 预测一个Instance的label  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;double[] distributionForInstance(Instance instance)&lt;/code&gt; :对于每一个可能的类, 给一个probability, 返回一个double数组  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以程序里训练model只需要调用&lt;code&gt;buildClassifier()&lt;/code&gt;函数即可.   &lt;/p&gt;
&lt;h1 id="5-model"&gt;5. 从文件读入数据和model&lt;/h1&gt;
&lt;p&gt;之前讲的是在程序里得到数据, 在程序里储存结果的方法, 而如果可以保存数据到文件的话, 在GUI界面下调试模型应该更加放方便.   &lt;/p&gt;
&lt;p&gt;预先已经得到了数据的话, 可以先把数据保存问arff格式, 然后用GUI的weka训练和调试参数. 当得到满意的结果以后可以在GUI界面里选择保存训练好的模型(一个.model文件): &lt;br/&gt;
&lt;img alt="" class="img-responsive" src="../images/java-use-weka/pasted_image001.png"/&gt; &lt;/p&gt;
&lt;p&gt;然后, weka提供了非常方便的方法, 直接从arff文件里得到&lt;code&gt;Instances&lt;/code&gt;对象, 从model文件里得到&lt;code&gt;Classifier&lt;/code&gt;对象: &lt;br/&gt;
(参考链接: &lt;a href="https://weka.wikispaces.com/Serialization"&gt;https://weka.wikispaces.com/Serialization&lt;/a&gt; 以及 &lt;a href="https://weka.wikispaces.com/Use+Weka+in+your+Java+code"&gt;https://weka.wikispaces.com/Use+Weka+in+your+Java+code&lt;/a&gt;)  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Classifier clf = (Classifier) weka.core.SerializationHelper.read("/some/where/j48.model");  &lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;Instances testset = new Instances(new BufferedReader(new FileReader("/some/where/test.arff")));``&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="6-evaluation"&gt;6. 输出Evaluation统计&lt;/h1&gt;
&lt;p&gt;当得到了训练好的模型&lt;code&gt;clf&lt;/code&gt;以及要使用的测试数据&lt;code&gt;testset&lt;/code&gt;以后, 可以在testset上测试模型, 并输出结果的统计数据. 这些是靠&lt;code&gt;Evaluation&lt;/code&gt;类完成的.&lt;br/&gt;
&lt;a href="http://weka.sourceforge.net/doc.stable-3-8/weka/classifiers/evaluation/Evaluation.html"&gt;http://weka.sourceforge.net/doc.stable-3-8/weka/classifiers/evaluation/Evaluation.html&lt;/a&gt;&lt;br/&gt;
Evaluation的构造函数里提供的Instances应该为training set, 这个训练集的作用是"to get some header information and prior class distribution information", 如果构造时给的是testing set的话, 应该调用&lt;code&gt;useNoPriors()&lt;/code&gt;函数一下.   &lt;/p&gt;
&lt;p&gt;构造了evalation对象以后, 只要使用 &lt;code&gt;evaluateModel(Classifier classifier, Instances data)&lt;/code&gt; 函数即可, 第一个参数为训练好了的模型(&lt;code&gt;clf&lt;/code&gt;), 第二个参数为要用来测试的数据(&lt;code&gt;testset&lt;/code&gt;).   &lt;/p&gt;
&lt;p&gt;然后可以输出统计信息, 就像在wekaGUI界面一样, 主要靠&lt;code&gt;toSummaryString()&lt;/code&gt;和&lt;code&gt;toMatrixString()&lt;/code&gt;两个函数.   &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Instances trainInstances = ... instances got from somewhere  &lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;Instances testInstances = ... instances got from somewhere  &lt;/span&gt;
&lt;span class="code-line"&gt;Classifier scheme = ... scheme got from somewhere&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;Evaluation evaluation = new Evaluation(trainInstances);  &lt;/span&gt;
&lt;span class="code-line"&gt;evaluation.evaluateModel(scheme, testInstances);  &lt;/span&gt;
&lt;span class="code-line"&gt;System.out.println(evaluation.toSummaryString());  &lt;/span&gt;
&lt;span class="code-line"&gt;System.out.println(evaluation.toMatrixString());&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="7"&gt;7. 输出预测结果&lt;/h1&gt;
&lt;p&gt;对于每一个Instance, 只需要调用Classifier的&lt;code&gt;classifyInstance(Instance instance)&lt;/code&gt;或者&lt;code&gt;distributionForInstance(Instance instance)&lt;/code&gt;函数, 即可得到预测结果...   &lt;/p&gt;
&lt;p&gt;Voila, 大概就是这样, weka这个工具还是蛮好用的(只要能忍受它界面的丑), 而且也算没有太多的坑...   &lt;/p&gt;</content><category term="soft"/><category term="ml"/><category term="weka"/><category term="java"/></entry><entry><title>使用Eclipse的UML插件生成类图</title><link href="https://x-wei.github.io/soft/%E4%BD%BF%E7%94%A8Eclipse%E7%9A%84UML%E6%8F%92%E4%BB%B6%E7%94%9F%E6%88%90%E7%B1%BB%E5%9B%BE.html" rel="alternate"/><published>2014-05-31T00:00:00+02:00</published><updated>2014-05-31T00:00:00+02:00</updated><author><name>mx</name></author><id>tag:x-wei.github.io,2014-05-31:/soft/使用Eclipse的UML插件生成类图.html</id><summary type="html">&lt;p&gt;Created samedi 31 mai 2014UML就是可以把程序的结构用图的形式表达出来的东西(好像叫类图), 虽然写程序的时候不大会用到这种东西来搞, 但是写报告的时候如果能够加上一张图的话, 就可 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Created samedi 31 mai 2014UML就是可以把程序的结构用图的形式表达出来的东西(好像叫类图), 虽然写程序的时候不大会用到这种东西来搞, 但是写报告的时候如果能够加上一张图的话, 就可以少费些口舌来解释代码了, 而且还有一种高大上的赶脚... 所以写完程序写报告的时候可以用一下. &lt;/p&gt;
&lt;p&gt;废话不多说, 看看我最后生成的UML图:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-responsive" src="../images/./eclipse的UML插件/pasted_image.png"/&gt;&lt;/p&gt;
&lt;p&gt;这张图表示一个抽象类&lt;code&gt;Operration&lt;/code&gt;有三个子类, 然后他们之间的关系... 如果用文字的话要解释半天吧...&lt;/p&gt;
&lt;p&gt;这张图是用&lt;a href="http://green.sourceforge.net/"&gt;Green UML&lt;/a&gt;做出来的, 这是一个eclipse插件, 安装方法为:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在eclipse里, &lt;code&gt;Help-&amp;gt;Install New Software&lt;/code&gt; 然后Add这个URL: &lt;a href="http://www.cse.buffalo.edu/faculty/alphonce/green"&gt;http://www.cse.buffalo.edu/faculty/alphonce/green&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;然后一路Next安装就可以了...&lt;/li&gt;
&lt;li&gt;如果老师显示pending, 可能是代理的问题(在X非常不爽的一点...哎...), 不过没事, 代理的设置在: &lt;code&gt;window → preference → General → Network Connections&lt;/code&gt;, 填上就应该好了...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" class="img-responsive" src="../images/./eclipse的UML插件/pasted_image001.png"/&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用Green UML生成类图的时候, 在java文件上点击右键, 选项里有Green UML的选项:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" class="img-responsive" src="../images/./eclipse的UML插件/pasted_image002.png"/&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;然后就OK了...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外还在网上找到了&lt;a href="http://www.modelgoon.org/"&gt;model goon&lt;/a&gt;, 不过它生成的类图貌似没有把所有信息都标上, 而且不太好看...&lt;/p&gt;</content><category term="soft"/><category term="java"/><category term="eclipse"/></entry><entry><title>linux下安装并使用java开发opencv的配置</title><link href="https://x-wei.github.io/tech/linux%E4%B8%8B%E5%AE%89%E8%A3%85%E5%B9%B6%E4%BD%BF%E7%94%A8java%E5%BC%80%E5%8F%91opencv%E7%9A%84%E9%85%8D%E7%BD%AE.html" rel="alternate"/><published>2014-02-10T00:00:00+01:00</published><updated>2014-02-10T00:00:00+01:00</updated><author><name>mx</name></author><id>tag:x-wei.github.io,2014-02-10:/tech/linux下安装并使用java开发opencv的配置.html</id><summary type="html">&lt;p&gt;今天花了四个小时, 终于在linux下把eclipse下java开发opencv给搞定了... 至于为什么花这么久的时间... 且听我慢慢讲... &lt;/p&gt;
&lt;h2 id="linuxopencv"&gt;linux编译安装opencv&lt;/h2&gt;
&lt;p&gt;首先, linux下安装opencv其实不麻烦的, 参考文档即可完成:
&lt;a href="http://docs.opencv.org/trunk/doc/tutorials/introduction/linux_install/linux_install.html"&gt;http://docs.opencv.org/trunk/doc/tutorials/introduction …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;今天花了四个小时, 终于在linux下把eclipse下java开发opencv给搞定了... 至于为什么花这么久的时间... 且听我慢慢讲... &lt;/p&gt;
&lt;h2 id="linuxopencv"&gt;linux编译安装opencv&lt;/h2&gt;
&lt;p&gt;首先, linux下安装opencv其实不麻烦的, 参考文档即可完成:
&lt;a href="http://docs.opencv.org/trunk/doc/tutorials/introduction/linux_install/linux_install.html"&gt;http://docs.opencv.org/trunk/doc/tutorials/introduction/linux_install/linux_install.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;大致有以下几个步骤:&lt;/p&gt;
&lt;p&gt;1) 安装gcc以及cmake等等乱七八糟的软件(不过ubuntu下默认差不多都有了吧...)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install build-essential python-dev cmake&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;2) 下载opencv-2.4.8.zip并解压缩&lt;/p&gt;
&lt;p&gt;3) 新建一个build文件夹&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cd ~/opencv&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;mkdir build&lt;/span&gt;
&lt;span class="code-line"&gt;cd build&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;4) 在终端里输入: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;make&lt;/span&gt;
&lt;span class="code-line"&gt;sudo make install&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;make命令会花费几十分钟时间...
然后&lt;strong&gt;理论上&lt;/strong&gt;就结束了... 如果不用java开发的话 就OK了 比如 可以运行sample文件夹下的python代码...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;但是&lt;/strong&gt;, 如果要使用java开发的话 需要接着这样做.....&lt;/p&gt;
&lt;h2 id="opencv-java"&gt;安装opencv-java&lt;/h2&gt;
&lt;p&gt;这一步非常DT, 因为官网上还有一个文档, 专门讲怎么用java开发的...
&lt;a href="http://docs.opencv.org/doc/tutorials/introduction/desktop_java/java_dev_intro.html"&gt;http://docs.opencv.org/doc/tutorials/introduction/desktop_java/java_dev_intro.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;1) 首先, 需要安装ant: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install ant&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;2) 其次 需要运行cmake, 关键是cmake的参数, 官网给的是这样的: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JAVA_HOME&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jvm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="c1"&gt;#这句不加应该也可以的&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;cmake&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;DBUILD_SHARED_LIBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;注意看输出的, 如果"To be built"里面有java这一项的话, 就&lt;strong&gt;应该&lt;/strong&gt;是OK的.... 接下来只要&lt;code&gt;make -j8&lt;/code&gt; 就可以了...&lt;/p&gt;
&lt;p&gt;最坑爹的地方来了, 以这样的参数运行cmake以后, 运行&lt;code&gt;make -j8&lt;/code&gt;总是不成功, 说有错误.....&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-responsive" src="../images/./linux下安装并使用java开发opencv的配置/pasted_image.png"/&gt;&lt;/p&gt;
&lt;p&gt;查了半天, 发现这是一个BUG:
&lt;a href="http://code.opencv.org/issues/2859"&gt;http://code.opencv.org/issues/2859&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;那么试一试加上参数: &lt;code&gt;-DBUILD_TESTS=OFF&lt;/code&gt; 吧...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;所以cmake的参数要这样写才可以&lt;/strong&gt;: &lt;/p&gt;
&lt;p&gt;&lt;code&gt;cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF ..&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;3) 用上面那样的参数运行cmake以后, 再: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;make -j8&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;sudo make install&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这样就可以成功make了...&lt;/p&gt;
&lt;h2 id="_1"&gt;如何判断是否安装成功?&lt;/h2&gt;
&lt;p&gt;以上操作结束后, 看看build文件夹, bin目录下是不是有一个&lt;code&gt;opencv-248.jar&lt;/code&gt;文件:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-responsive" src="../images/./linux下安装并使用java开发opencv的配置/pasted_image001.png"/&gt;&lt;/p&gt;
&lt;p&gt;如果有的话 就说明成功安装了opencv的java组件... &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;!!注意!!&lt;/strong&gt;
&lt;strong&gt;不能用windows下opencv安装目录下的那个opencv-248.jar&lt;/strong&gt;!! 
刚才生成那个jar和windows下的jar不一样的!! (我查了MD5码... 其实看文件大小也能看出来!!)&lt;/p&gt;
&lt;h2 id="eclipse"&gt;Eclipse下的配置&lt;/h2&gt;
&lt;p&gt;这里有一篇非常好的帖子, 写的非常到位, 我就不重复了, 链接:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://exintopro.net/blog/2013/10/02/setting-up-eclipse-for-using-opencv-java-in-ubuntu/"&gt;http://exintopro.net/blog/2013/10/02/setting-up-eclipse-for-using-opencv-java-in-ubuntu/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个帖子虽然很好, 但是没有介绍编译的那一部分, 由于安装java组件时的编译过程和官网给的不一样, 所以才导致我废了半天的时间啊!......&lt;/p&gt;</content><category term="tech"/><category term="eclipse"/><category term="java"/><category term="opencv"/></entry><entry><title>java线程小结</title><link href="https://x-wei.github.io/tech/java%E7%BA%BF%E7%A8%8B%E5%B0%8F%E7%BB%93.html" rel="alternate"/><published>2013-11-29T00:00:00+01:00</published><updated>2013-11-29T00:00:00+01:00</updated><author><name>mx</name></author><id>tag:x-wei.github.io,2013-11-29:/tech/java线程小结.html</id><summary type="html">&lt;p&gt;INF422的TD2, 这节TD是要做一个多线程筛选质数的程序, 关于java的多线程, 以前用过但是不知道啥意思, 在这里总结下. &lt;/p&gt;
&lt;h2 id="_1"&gt;创建进程&lt;/h2&gt;
&lt;p&gt;为了实现多线程, 需要定义一个新的class, 有两种方法 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;INF422的TD2, 这节TD是要做一个多线程筛选质数的程序, 关于java的多线程, 以前用过但是不知道啥意思, 在这里总结下. &lt;/p&gt;
&lt;h2 id="_1"&gt;创建进程&lt;/h2&gt;
&lt;p&gt;为了实现多线程, 需要定义一个新的class, 有两种方法: 
&lt;strong&gt;或者继承自&lt;/strong&gt;&lt;code&gt;Thread&lt;/code&gt;&lt;strong&gt;类, 或者实现&lt;/strong&gt;&lt;code&gt;Runnable&lt;/code&gt;&lt;strong&gt;接口&lt;/strong&gt;(关键是重载run()方法). &lt;/p&gt;
&lt;h3 id="thread"&gt;继承自Thread类&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;写法1: 定义一个继承自Thread的内部类--&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;类名&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;方法&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;方法&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;；&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="n"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;属性&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;；&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;属性&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;；&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;或者用下面种&lt;strong&gt;内联(inline)&lt;/strong&gt;的写法, 不用给这个类起名字了(不过还要给这个实例取名字): &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;private Thread [实例名] = new Thread () {&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;    public void run() {&lt;/span&gt;
&lt;span class="code-line"&gt;    // ...&lt;/span&gt;
&lt;span class="code-line"&gt;    }&lt;/span&gt;
&lt;span class="code-line"&gt;} ;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;然后让进程开始, 就是: 
&lt;code&gt;t.start();&lt;/code&gt;
如果用&lt;code&gt;t.run()&lt;/code&gt;的话, 则依然是并行执行的, 可能达不到多线程效果...&lt;/p&gt;
&lt;h3 id="runnable"&gt;实现Runnable接口&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;方法1, 代码: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;类名&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Runnable&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="nx"&gt;方法1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="nx"&gt;方法2&lt;/span&gt;&lt;span class="err"&gt;；&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="nx"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// other code…&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="nx"&gt;属性1&lt;/span&gt;&lt;span class="err"&gt;；&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="nx"&gt;属性2&lt;/span&gt;&lt;span class="err"&gt;；&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;方法2, 内联写法:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;private Runnable [实例名] = new Runnable() {&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;public void run() {&lt;/span&gt;
&lt;span class="code-line"&gt;    //...&lt;/span&gt;
&lt;span class="code-line"&gt; }&lt;/span&gt;
&lt;span class="code-line"&gt;};&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="android_1"&gt;android上需要注意的一点&lt;/h2&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;"Android modifies the user interface and handles input events from &lt;strong&gt;one single&lt;/strong&gt; user interface thread. This thread is also called &lt;strong&gt;the main thread&lt;/strong&gt;."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Android collects all events in a queue and processed an instance of the Looper class.
&lt;img alt="" class="img-responsive" src="../images/./java线程小结/pasted_image.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;所以注意要修改用户交互的组件(View, Toast, ect.)的时候, 需要在main Thread里面操作, 否则运行时会出错!!&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;那么, 当其他线程进行计算完成以后, 要刷新屏幕的显示时, 需要告知main Thread 进行更新显示:&lt;/p&gt;
&lt;p&gt;"Ajouter un nouvel objet comportant une méthode run() mettant à jour le nombre d'entier premiers (nouvel objet implémentant l'interface Runnable). À la fin du crible, le thread de calcul devra alors envoyer un message (ce nouvel objet) au thread principal pour mettre à jour l'affichage graphique. Cette mise à jour doit être faite via un appel à la méthode post() d'une instance de la classe Handler (l'objet Handler doit être instancié dans le thread principal)."&lt;/p&gt;
&lt;p&gt;Bref, 要做到多线程计算, 计算结果显示在屏幕上, 需要:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;添加一个Runnable实例("一个实现了Runnable接口的类的实例"), 重载run()方法实现calcul&lt;/li&gt;
&lt;li&gt;&lt;em&gt;一个&lt;/em&gt;&lt;a href="http://developer.android.com/reference/android/os/Handler.html"&gt;Handler&lt;/a&gt;&lt;em&gt;实例, 然后调用这个Handler的post()方法.&lt;/em&gt; &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;看看文档里是咋说的: &lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;public final boolean post (Runnable r)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Added in API level 1
Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.&lt;/p&gt;
&lt;p&gt;Parameters
r   The Runnable that will be executed.
Returns
Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting.&lt;/p&gt;
&lt;p&gt;意思是&lt;code&gt;handler.post(r)&lt;/code&gt;会把r(一个Runnable实例)加入message queue中去, &lt;em&gt;这个Runnable会在这个handler关联的Thread中执行&lt;/em&gt;. 所以只要handler关联的是main Thread, 就可以在这个Runnalbe里面写graphic的代码也不会出错了. &lt;/p&gt;
&lt;p&gt;如果在Activity类的声明里声明handler为一个属性: 
&lt;code&gt;private Handler handler = new Handler();&lt;/code&gt;
这个构造函数没有参数, 根据文档, "Default constructor associates this handler with the Looper for the current thread." 所以这个handler关联到了current thread, 也就是main Thread.....&lt;/p&gt;
&lt;h2 id="_2"&gt;例子&lt;/h2&gt;
&lt;p&gt;所以, 多线程计算, 计算结束后修改屏幕显示的话, 需要以下__三个步骤__(比上面的俩步骤多了一个, 不知道是否还可以简化): &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在主线程里声明handler, (声明成Activity的一个属性): &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;private Handler handler = new Handler();&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;写一个用于修改屏幕显示的Runnable r(也声明成一个属性了):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;private Runnable r = new Runnable() {&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;public void run() {&lt;/span&gt;
&lt;span class="code-line"&gt;//code to update graphic display...&lt;/span&gt;
&lt;span class="code-line"&gt;}&lt;/span&gt;
&lt;span class="code-line"&gt;};&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;再写一个进行计算的Thread t, 在计算结束后, 用handler.post(r)实现刷新显示的效果: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;run()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;//...code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;calculating...&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;//结束计算以后,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;刷新屏幕:&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;handler.post(r)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;然后在onCreate()函数里, 让Thread t 启动起来: &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;t.start();&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;需要让t一直循环(监视某个flag), 当flag变为true的时候, 进行计算.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;为了达到这个效果, Thread t里面的run()方法需要这样写:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;/code&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;flag&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;{&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;...&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;calculation&lt;/span&gt;...&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;handler&lt;/span&gt;.&lt;span class="nv"&gt;post&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;false&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;            &lt;/span&gt;}&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;        &lt;/span&gt;}&lt;span class="w"&gt;   &lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="w"&gt;    &lt;/span&gt;}&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="process-threadrunnable"&gt;Process, Thread和Runnable的区别?&lt;/h2&gt;
&lt;p&gt;线程(Thread)是指进程(Process)中的一个执行流程，一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程，进程中的多个线程共享进程的内存。&lt;/p&gt;
&lt;p&gt;参考链接: 
&lt;a href="http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html"&gt;http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html&lt;/a&gt;
&lt;a href="http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html"&gt;http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html&lt;/a&gt;
&lt;a href="http://developer.android.com/reference/android/os/Handler.html"&gt;http://developer.android.com/reference/android/os/Handler.html&lt;/a&gt;
&lt;a href="http://lavasoft.blog.51cto.com/62575/99150"&gt;http://lavasoft.blog.51cto.com/62575/99150&lt;/a&gt;&lt;/p&gt;</content><category term="tech"/><category term="android"/><category term="java"/></entry></feed>