先自问一个问题:C++有几种new?
我一直以为是两种:operator new 和 placement new。刚刚查了下,原来是3种:还有一个是new operator。而且,我还弄错了一个...但是,无论如何,我们能够改变的只有两个:
1、operator new,分配内存。
2、placement new,构造对象。
而剩下的那个new operator很直白:负责调用上面两个new。也就是其仅仅是语法层次上的东西,用来产生operator new和placement new的语义。
这是一个不错的开始,因为我要讲的“内存管理”,其实是上面所提到的所有:内存分配和对象构造。当然,还有一个对称的内存释放和对象析构,这些自然也会有,只是相对来说前者更加直白和重要。或者,我可以换一个题目:内存与对象管理技术。
这将是一个,或者说数个相当大的话题;你不信,我可以给你一个列表(别眨眼):
1、内存池,特别是一个可用的内存池,构建一个是相当困难的!其需要达到数个极其苛刻的要求:强悍的性能(否则我们还需要它?)、并发且线程安全(这点和上一点几乎是矛盾的存在)、高可用性(意味着其有着合理的回收机制,否则可能会浪费大量内存;而且能够处理相当畸形的环境,比如单一线程分配,单一线程回收)、可调试(简直不可能!!!)。
2、线程模型,任何涉及并发的技术,都需要一个强大的线程模型,以提供各种额外的支持;为什么会提到它?内存分配不需要并发?不要开玩笑。没有TLS(线程本地存储),一切的并发都只能吃翔;而这却需要一个新的线程模型的支撑(系统的TLS,我个人而言,并不信任)。
3、对象构造管理,这其实是一个很庞大的工程;其处于整个C++的最底层,也就意味着,我需要足够的努力才能够去完成我想要达到的目标——对于不同的类型,我能够做出正确且最好的选择,来构造它。
4、类型系统,这是作为第三条的支撑性系统;如何达到上一条的目标?我需要一个类型系统,来提供足够的信息,以完成选择(需要注意的是:对象构造本身和类型系统,是独立的;只是恰巧,类型系统可以帮助对象获得最优的构造方式)。
5、垃圾收集器,这是一个C++“永远的痛”,特别是当我用C++创造了一门有垃圾收集的脚本语言时,深感如此;所以,我陆续构建了两套垃圾收集系统,以C++可用的方式,当然会有各种限制。这里,提到的原因很简单:我们都梦想着能够用上或者创造一个属于C++的垃圾收集器!!! 特别是,在我做完上面的所有事情后。
看到没有,上面任何一个部分,都是一个庞大的话题;所幸的是,这些我都完整地做了一遍(或多遍),我会慢慢地,详细到来。
PS:写这部分,我是很高兴和激动的,因为,这正是我所最擅长的领域;而身边却没有一个可交流的人。
一、内存池
所有的STL容器,都有着一个不可忽视,但一直被无视的部分:内存适配器;其实,也就是一个预留的接口,某天我们能够使用更快的内存分配,来替换默认的malloc/free。毫无疑问,这就是内存池。许多书籍都提到并给出了详细的代码,来教会我们如何构建一个性能秒杀系统分配的单线程内存池;而在并发上,也就是支持多线程的内存池上,支支吾吾,止步于加锁...最后发现和系统分配并没有什么太大区别,毕竟系统分配也是加锁了的。
当然,要构建一个可用的高性能多线程内存池,并不困难;国内的还有人,特意写了一本书,来讲解他自己命名的多线程内存池(当我发现他所实现的高端货,和我自己折腾出来的一模一样时,便没看了:因为,造出来所需要的努力,其实远比写一本书少的多;当然,后者钱要多得多)。其思路很简单:
1、每一个线程一个内存池;通过TLS实现。
2、一个所有线程共用的全局内存池;用来给线程内部的池,提供分配和回收服务;当然,这一级访问需要锁~
3、线程内部池的分配回收策略(向共用池),共用池整体的分配回收策略(向系统)。
之所以“简单”,是前两个部分,是很直白和自然的解决方案!只要你记住一点:我要并发,我要性能——请问TLS。而需要思考和抉择的是第三点;之所以需要“思考”,因为没有超大规模数据的支撑的前提下,任何的策略都只是我们的臆想而已,任何可能的畸形分配情形,都会使我们所“猜测”出的策略无效;而“抉择”,是在我们了解到了足够信息后,必然需要面对的(否则,系统分配,还会有存在的理由?)。
所以,在面对一个“可用”的内存池时,我们需要足够的谨慎;而,我所要讲的就是这些“谨慎”。
二、线程模型
或许,我过于依赖TLS,因为我足够愚蠢:除此之外,我别无他法。
在我所提到的内存池中所使用的关键技术之一便是TLS;同样的在垃圾收集器部分,也将大量运用到TLS技术。所以,是的我们无法避开线程模型:因为,TLS需要一些额外的支持,恰巧C++没有给我们(所以,我只能自己去造)。
为什么,我不用Windows的TLS?主要原因是,我不信任它(属于个人直觉);另外的一部分,则是我的库中是尽量避免任何第三方依赖!包括STL,我也不会用到(所以,我自己写了一套;还有更深层次的原因:我不喜欢STL的现有部分接口方式)。
什么是线程模型?我不知道。看到那么多人和大牛都在说,所以我也用了这个关键字。在我的库里就是:
1、重新定义的一整套接口,用来提供完整的线程服务;我使用了类似Java的方式,只要继承了IThread,然后实现run,便可开启另外一个线程:
class MyThread: public IThread{
void run(){
...
}
};
MyThread thread;
thread.execute();//启动线程 2、一个线程服务类,用于提供各种线程相关服务;其中最关键的服务就是TLS;还有一个稍微有一点霸气的功能:stop the world。也就是,它管理着当前所有运行着的线程,包括主线程。
3、线程工具类,TaskRunner、Thread、Timer、ThreadPool提供了各种不同的线程支持。
4、并发工具类,进行了抽象化后的锁和事件;当然重要的是锁:内核锁、临界区、读写锁。
所有的这些都是简单而无聊的;但作为一个整体来提供,则需要付出许多额外的努力。
三、对象构造
用“构造”这个词来限定这个领域;很不正确,毕竟完整的是:无参数构造(默认构造)、有参数构造、复制构造、对象析构、对象移动。一共5个部分需要我们关心,如果你还不明白,看看下面的代码:
Something* addr = (Something*)std::malloc(sizeof(Something));
//1、无参数构造
new (addr)Something();//调用Something();
//2、有参数构造
new (addr)Something(12);//调用Something(int);
//3、复制构造
Something value;
new (addr)Something(value);//调用Something(const Something&);
//4、对象析构
addr->~Something();//调用~Something();
//5、对象移动
Something* other= (Something*)std::malloc(sizeof(Something));
new (other)Something(*addr);//将addr处的对象移到other
addr->~Something();//析构掉addr的对象;只保留other处的,保证“移动”语义 上面都是最保守的方式;对于基本类型,以及自定义POD类型,我们并不需要这样“复杂”的调用:
在工作当中,我们难免会遇到这样的适应屏幕需求,宽版以1200px为基准,窄版以1024为基准,版心应该怎么设置呢?而合理运用媒体查询就能非常容易帮我们解决这个问题。 /*版心*/ @media screen and (max-width:1200px) and (min-width:1024px){ .w{ width:1024px; margin:0 auto; position: relative; } } @media screen and (max-width:1024px){ .w{ width:960px; margin:0 auto; position: relative; } } @media screen and (min-width:1200px){ .w{ width:1200px; margin:0 auto; position: relative; } }
VM options:
-mx2048m -XX:MaxPermSize=2048m -Drebel.spring_plugin=true -Drebel.hibernate_plugin=true
在网上下载了离线版的菜鸟教程,最后发现解压后无法用浏览器直接打开,以下为解决方法:
1.打开浏览器,我用的是手机qq浏览器,
2.进入文件下载,
3.我的文件--手机存储
4.在本地存储空间直接找到html文件就能直接打开了。
ps:其它手机浏览器也都差不多。
每次启动Ubuntu都显示System program problem detected,很烦人,不过修改一个文件就可以。
执行命令:
sudo gedit /etc/default/apport 将enabled=1改为enabled=0保存退出即可
对于横向的GridView,很多人会说,没必要,用RecycleView就可以完成,但是,我就喜欢搞点特别的,因此当初就写了个横向的GridView。网上的东西大部分都有很多其它的东西,比如你要找一个功能,它会给你十个,然后你要去改,还不如自己写出来。。我的原则就是一切以简单为主。
主要代码:
DisplayMetrics dm =new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); float density = dm.density; int gridviewWidth = (int) (size * (length) * density); int itemWidth = (int) (length * density); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( gridviewWidth, LinearLayout.LayoutParams.MATCH_PARENT); mygridview.setLayoutParams(params); // 设置GirdView布局参数,横向布局的关键 mygridview.setColumnWidth(itemWidth); // 设置列表项宽 // gridsetRankPotentialActorGridViewView.setHorizontalSpacing(20); // 设置列表项水平间距 mygridview.setStretchMode(GridView.NO_STRETCH); mygridview.setNumColumns(size); // 设置列数量=列表集合数 xml布局主要代码: <HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_marginRight="5dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginBottom="10dp"> <demo.leo.com.horizontalgridview.MyGridView android:id="@+id/mygridview" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:numColumns="auto_fit" android:scrollbars="none" android:stretchMode="spacingWidthUniform" /> </LinearLayout> </HorizontalScrollView> 话不多说,直接上传文件,另外附赠一个全能的ViewHolder
一、表格环境的定义 环境tabular和tabular*是生成表格的基本工具,其定义(语法)如下: \begin{tabular}[位置]{列}
行
\end{tabular} \begin{tabular*}{宽度}[位置]{列}
行
\end{tabular*} tabular环境可以用来排版带有横线和竖线的表格,LATEX自动确定表格的宽度;tabular*环境与tabular环境类似,只是可以用参数指定表格的整体宽度,另外列参数必须在第一列后面的某个地方包含一个合适的表达式(见下面说明)。 通常,为了使表格在页面上居中,要利用center环境: \begin{center}
表格
\end{center} 二、表格环境参数格式 2.1 位置可选参数 该参数表示表格相对于外部文本行基线的位置,又称为垂直定位参数,有三种情况: t: 表格顶部与当前外部文本行的基线重合 b: 表格底部与当前外部文本行的基线重合 缺省(不使用): 表格按照外部文本行的基线垂直居中
2.2 列必选参数 该参数表明表格的格式,故又称为列格式参数。在这个参数中,对每一列必须有一个相应的格式符号,另外还可能包含相应于表格左右边界和列间距的其它项。列格式符号可以取下列值: l: 列中文本左对齐 r: 列中文本右对齐 c: 列中文本居中 pf宽度g: 指定列的文本宽度,宽度由宽度参数给出,列中文本按该宽度自动换行 |: 画一条竖直线 ||: 画二条紧相邻的竖直线
三、 表格文本行中的命令 表格中的每一水平行都由\结束。这些行由一组彼此之间用&符号分开的列条目组成。因此每一行应具有与列定义中列中相同数目的列条目,其中有些条目可以是空白的。 3.1 \tabularnewline命令 \tabularnewline命令用于强制一表格行的结束,而\除了可以结束整个一行表格内容外,还可以在单个列的内容中实现换行.
3.2 \ hline命令 这条命令只能位于第一行前面或紧接在行结束命令\的后面,表示在刚结束的那一行画一根水平的直线。如果这条命令位于表格的开头,那么就会在表格顶部画一横线,横线的宽度与表格的宽度相同. 放在一起的两条水平\hline命令就会画出两条间隔很小的水平线.
3.3 \cline{n-m}命令 这条命令的放置同\hline命令,并且在一行中可以出现多次。该命令从第n列的左边开始,画一条到第m列右边结束的水平线.
3.4 \ vline命令 该命令画一条竖直线,其高度等于其所在行的行高。用这种命令,可以得到那些不是贯穿整个表格的竖直线.
3.5 \multicolumn{数}{列}{文本}命令 这条命令只能位于一行的开始或者一个列分隔符(&)的后面,它把接下来的数个列合并成一个列处理,其内容为文本。该列的总宽度等于合并前各个列的宽度之和加上列间距之和。列参数的含义与tabular环境中列参数相似。
3.6 @表达式:@文本 @表达式在出现两列中间的每一行上插入文本,同时去掉原来在这两列间自动插入的 空白。我们有下面的几点为变通: 1. 如果我们需要继续使用空白,必须在@表达式的文本参数中包含\hspace{}命令。 2. 如果希望某两个特定列之间的间隔与缺省的标准间隔不同,可以在表格环境的行参数中相应的位置上放上@{\hsapce{宽度}}控制,此时该处列间间隔将变成宽度。 3. @表达式中使用\extracolsep{宽度}控制,使后面所有列间间隔在原来标准间隔的基础上增加宽度大小。 4.
欢迎使用Markdown编辑器写博客 Python对于文件操作非常方便,很大一部分是因为os这个库,在做优达城深度学习作业的时候里面有一堆os,各种列表推导式混合os.path,一下就绕晕了。这里做点笔记,方便自己学习&复习。
如上图,我当前目录是/home/mao/tensorflow-master/tensorflow/examples/udacity
在我当前目录下有 1.os.path.exists('notMNIST_large') 返回True
2.os.stat('notMNIST_large.tar.gz') 返回的答案是posix.stat_result(st_mode=33270, st_ino=1448325, st_dev=2049, st_nlink=1, st_uid=1000, st_gid=1000, st_size=247336696, st_atime=1484708728, st_mtime=1484663203, st_ctime=1484708728)其中st_size是该文件的大小,单位是Byte
3.os.path.splitext('notMNIST_large.tar.gz') 返回的是('notMNIST_large.tar', '.gz')
4.os.path.join('notMNIST_large', 'A') 返回的是 ‘notMNIST_large/A’
5.os.listdir('notMNIST_large') 返回的是该路径下所有文件名字 ['I', 'E.pickle', 'B', 'A.pickle', 'G', 'D.pickle', 'J', 'F', 'E', 'G.pickle', 'J.pickle', 'C', 'D', 'H.pickle', 'B.pickle', 'I.pickle', 'A', 'C.pickle', 'H', 'F.pickle']
6.来个列表推导式和os混合起来的爽一爽
root = os.path.splitext(os.path.splitext('notMNIST_large')[0])[0] [os.path.join(root, d) for d in sorted(os.listdir(root)) if os.path.isdir(os.path.join(root, d))] 分析一下:首先是 这个root的答案是notMNIST_large,因为内层的splitext[0]的结果是notMNIST_large.tar,然后外层的splitext[0]的结果是notMNIST 接着我们看列表推导式这里: 先看for d in sorted(os.listdir(root)),这个的结果是把notMNIST_large下面的所有文件文件夹按照顺序排列好赋给d。 答案是
A A.pickle B B.
(39)dom.append()与$.append()
通过原生js获取到的dom,和通过jQuery获取到的dom,都有append方法,但是他们表现出来的效果是有所区别的。
具体来说,如代码:
<div id="test1"></div> <div id="test2"></div> <script> var dom1 = document.getElementById("test1"); dom1.append('原生js获取的dom的append方法是不能:<b>加粗</b>和<em>斜体</em>的'); var dom2 = $("#test2"); dom2.append('jQuery获取到的dom的append方法是可以:<b>加粗</b>和<em>斜体</em>的'); </script> 显示结果是:
原生js获取的dom的append方法是不能:<b>加粗</b>和<em>斜体</em>的
jQuery获取到的dom的append方法是可以:加粗和斜体的
面试题(有答案):
1. String类为什么是final的。
答:主要是为了“效率” 和 “安全性” 的缘故。若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final。
2. HashMap的源码,实现原理,底层结构。
3. 说说你知道的几个Java集合类:list、set、queue、map实现类咯。。。
4. 描述一下ArrayList和LinkedList各自实现和区别
5. Java中的队列都有哪些,有什么区别。
6. 反射中,Class.forName和classloader的区别
答:共同点
1. 两者都会将用户指定的类加载到内存中,供用户使用
不同点:
Class.forName方法有要不要初始static变量的参数,而ClassLoader.loadClass()没有;Class.forName的重载方法是静态的,而ClassLoader.loadClass不是。
7. Java7、Java8的新特性(baidu问的,好BT)
8. Java数组和链表两种结构的操作效率,在哪些情况下(从开头开始,从结尾开始,从中间开始),哪些操作(插入,查找,删除)的效率高
答:数组在随机访问数据、随机增加数据、随机删除数据的执行效率上比链表的效率高,数据量越小,两者之间效率的差距越小,数据量越大差距越大。
9. Java内存泄露的问题调查定位:jmap,jstack的使用等等
10. string、stringbuilder、stringbuffer区别
11. hashtable和hashmap的区别
13 .异常的结构,运行时异常和非运行时异常,各举个例子
14. String a= “abc” String b = “abc” String c = new String(“abc”) String d = “ab” + “c” .他们之间用 == 比较的结果
15. String 类的常用方法
16. Java 的引用类型有哪几种
17. 抽象类和接口的区别
18. java的基础类型和字节大小。
response、request对象 Tomcat收到客户端的http请求,会针对每一次请求,分别创建一个代表请求的request对象、和代表响应的response对象
既然request对象代表http请求,那么我们获取浏览器提交过来的数据,找request对象即可。response对象代表http响应,那么我们向浏览器输出数据,找response对象即可。
什么是HttpServletResponse对象? http响应由状态行、实体内容、消息头、一个空行组成。HttpServletResponse对象就封装了http响应的信息。
HttpServletResponse的应用 调用getOutputStream()方法向浏览器输出数据 调用getOutputStream()方法向浏览器输出数据,getOutputStream()方法可以使用print()也可以使用write(),它们有什么区别呢?我们试验一下。代码如下 //获取到OutputStream流 ServletOutputStream servletOutputStream = response.getOutputStream(); //向浏览器输出数据 servletOutputStream.print("aaaa"); 成功输出,好像没什么毛病。 我们试着输出中文试试 //获取到OutputStream流 ServletOutputStream servletOutputStream = response.getOutputStream(); //向浏览器输出数据 servletOutputStream.print("中国!"); 出异常了!!! 为什么会出现异常呢?在io中我们学过,outputStream是输出二进制数据的,print()方法接收了一个字符串,print()方法要把“中国”改成二进制数据,Tomcat使用IOS 8859-1编码对其进行转换,“中国”根本对ISO 8859-1编码不支持。所以出现了异常我们再看看write()方法,先向浏览器输出英文数据 response.getOutputStream().write("aaa".getBytes()); 没有问题 再试试输出中文数据 response.getOutputStream().write("你好呀我是中国".getBytes()); 貌似也没有问题。 为什么使用write()方法能够正常向浏览器输出中文呢?"你好呀我是中国".getBytes()这句代码在转成byte[]数组的时候默认查的是gb2312编码,而“你好呀我是中国”支持gb2312编码,所以可以正常显示出来。但是,程序要实现通用性,应该使用的是UTF-8编码,我们在字符串转换成字节数组时指定UTF-8编码,看看会怎么样。 response.getOutputStream().write("你好呀我是中国".getBytes("UTF-8")); 好的,成功把它搞成乱码了!!! 为什么它变成了乱码呢?原因是这样的:我在向服务器输出的中文是UTF-8编码的,而浏览器采用的是GBK,GBK想显示UTF-8的中文数据,不乱码才怪呢! - 既然如此,我将浏览器的编码改成UTF-8试试。
乱码问题又解决了。可是,每次编写UTF-8程序时都要去网页上改编码格式吗?这样明显不可能的。既然HTTP响应有对浏览器说明回送数据是什么类型的消息头,那么HttpServletResponse对象就应该有相对应的方法告诉浏览器回送的数据编码格式是什么于是乎就去查找Servlet API,找到了设置消息头的方法 //设置头信息,告诉浏览器我回送的数据编码是utf-8的 response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.getOutputStream().write("你好呀我是中国".getBytes("UTF-8")); 浏览器在显示数据时,自动把页面的编码格式置换成UTF-8,乱码问题也解决了 另外,除了使用HttpServletResponse对象设置消息头的方法,我可以使用html的标签模拟一个http消息头
下面是代码:
//获取到servletOutputStream对象 ServletOutputStream servletOutputStream = response.getOutputStream(); //使用meta标签模拟http消息头,告诉浏览器回送数据的编码和格式 servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes()); servletOutputStream.write("我是中国".getBytes("UTF-8")); 乱码问题也可以解决 调用getWriter()方法向浏览器输出数据 对于getWriter()方法而言,是Writer的子类,那么只能向浏览器输出字符数据,不能输出二进制数据 使用getWriter()方法输出中文数据,代码如下: //获取到printWriter对象 PrintWriter printWriter = response.getWriter(); printWriter.write("看完博客点赞!"); 喜闻可见的事又出现了,我又出现乱码了。 为什么出现乱码了呢?由于Tomcat是外国人的写,Tomcat默认的编码是ISO 8859-1,当我们输出中文数据的时候,Tomcat会依据ISO 8859-1码表给我们的数据编码,中文不支持这个码表呀,所以出现了乱码既然如此,我设置一下编码不就好了吗,代码如下: //原本是ISO 8859-1的编码,我设置成UTF-8 response.
udp socket connect一个不存在的地址后调用sendto返回111错误(connect refused)
udp socket 可以调用connect,这个就不说,不了解的可以网上查资料,下面直接说返回111错误的原因
udp socket 发送流程 sendto->sock_sendmsg->__sock_sendmsg->udp_sendmsg->ip_make_skb->__ip_append_data->sock_alloc_send_skb->sock_alloc_send_pskb
到了sock_alloc_send_pskb这个函数里,在发送前会调用sock_error检查该socket是否有错误,如果有错误,就直接返回了,由于链接一个不存在的地址,所以sock_error检查失败,返回错误111(connection refused),sock_error代码如下,检查sk->sk_err
static inline int sock_error(struct sock *sk) { int err; if (likely(!sk->sk_err)) return 0; err = xchg(&sk->sk_err, 0); return -err; } 接下来再说一下sk->sk_err何时被置成111,通过用systemtap捕捉到 0xffffffff8148ad40 : udp_err+0x0/0x20 [kernel] 0xffffffff8148f6c0 : icmp_unreach+0x140/0x2d0 [kernel] 0xffffffff8148f430 : icmp_rcv+0x290/0x330 [kernel] 0xffffffff814621fd : ip_local_deliver_finish+0xdd/0x2d0 [kernel] 0xffffffff81462488 : ip_local_deliver+0x98/0xa0 [kernel] 0xffffffff8146194d : ip_rcv_finish+0x12d/0x440 [kernel] 0xffffffff81461ed5 : ip_rcv+0x275/0x350 [kernel] 0xffffffff8142bedb : __netif_receive_skb+0x49b/0x6e0 [kernel] 0xffffffff8142df88 : netif_receive_skb+0x58/0x60 [kernel] 0xffffffff8142e090 : napi_skb_finish+0x50/0x70 [kernel] 0xffffffff81430719 : napi_gro_receive+0x39/0x50 [kernel] udp_err调用的是__udp4_lib_err,由于链接一个不存在的地址,在发送数据包的时候,会返回一个icms 目标地址不可达的错误ICMP_DEST_UNREACH,在__udp4_lib_err函数的最后倒数第4行,将sk->sk_err置成了ECONNREFUSED(111),所以在发送数据包的时候,就检测到了这个错误
<div style="background-image:url(这里填写图片的路径}); background-repeat: no-repeat; background-position:center center; background-size: cover; width:165px;height:105px;"> </div> 其他属性没什么可说的,不懂自己百度,
最后一个属性,值得注意的两个值:cover和contain
因为w3school说的有点绕, 简单说明一下
cover:让图片填充满父节点,超出部分隐藏,仅显示中间,这才是我们想要的效果。
contain:让图片根据父节点宽高等比例缩放。
文章是转发天善大数据(https://www.hellobi.com/)的文章,文章没有链接。
数据分析师的能力体系 如下图: 数学知识 数学知识是数据分析师的基础知识。 对于初级数据分析师,了解一些描述统计相关的基础内容,有一定的公式计算能力即可,了解常用统计模型算法则是加分。 对于高级数据分析师,统计模型相关知识是必备能力,线性代数(主要是矩阵计算相关知识)最好也有一定的了解。 而对于数据挖掘工程师,除了统计学以外,各类算法也需要熟练使用,对数学的要求是最高的。 数学知识方面,还没有到达到数据挖掘工程师的级别,需要的就是算法的重新整理和熟练使用;
分析工具 对于初级数据分析师,玩转Excel是必须的,数据透视表和公式使用必须熟练,VBA是加分。另外,还要学会一个统计分析工具,SPSS作为入门是比较好的。 对于高级数据分析师,使用分析工具是核心能力,VBA基本必备,SPSS/SAS/R至少要熟练使用其中之一,其他分析工具(如Matlab)视情况而定。 对于数据挖掘工程师……嗯,会用用Excel就行了,主要工作要靠写代码来解决呢。 初级水平啊,VBA和R,另外SPSS和SAS的工具,最好配置。
编程语言 对于初级数据分析师,会写SQL查询,有需要的话写写Hadoop和Hive查询,基本就OK了。 对于高级数据分析师,除了SQL以外,学习Python是很有必要的,用来获取和处理数据都是事半功倍。当然其他编程语言也是可以的。 对于数据挖掘工程师,Hadoop得熟悉,Python/Java/C++至少得熟悉一门,Shell得会用……总之编程语言绝对是数据挖掘工程师的最核心能力了。 SQL和Python,努力的方向,两年没有学习shell了,搭载Linux系统很有必要。
业务理解 业务理解说是数据分析师所有工作的基础也不为过,数据的获取方案、指标的选取、乃至最终结论的洞察,都依赖于数据分析师对业务本身的理解。 对于初级数据分析师,主要工作是提取数据和做一些简单图表,以及少量的洞察结论,拥有对业务的基本了解就可以。 对于高级数据分析师,需要对业务有较为深入的了解,能够基于数据,提炼出有效观点,对实际业务能有所帮助。 对于数据挖掘工程师,对业务有基本了解就可以,重点还是需要放在发挥自己的技术能力上。
逻辑思维 这项能力在我之前的文章中提的比较少,这次单独拿出来说一下。 对于初级数据分析师,逻辑思维主要体现在数据分析过程中每一步都有目的性,知道自己需要用什么样的手段,达到什么样的目标。 对于高级数据分析师,逻辑思维主要体现在搭建完整有效的分析框架,了解分析对象之间的关联关系,清楚每一个指标变化的前因后果,会给业务带来的影响。 对于数据挖掘工程师,逻辑思维除了体现在和业务相关的分析工作上,还包括算法逻辑,程序逻辑等,所以对逻辑思维的要求也是最高的。
数据可视化 数据可视化说起来很高大上,其实包括的范围很广,做个PPT里边放上数据图表也可以算是数据可视化,所以我认为这是一项普遍需要的能力。 对于初级数据分析师,能用Excel和PPT做出基本的图表和报告,能清楚的展示数据,就达到目标了。 对于高级数据分析师,需要探寻更好的数据可视化方法,使用更有效的数据可视化工具,根据实际需求做出或简单或复杂,但适合受众观看的数据可视化内容。 对于数据挖掘工程师,了解一些数据可视化工具是有必要的,也要根据需求做一些复杂的可视化图表,但通常不需要考虑太多美化的问题。
协调沟通 对于初级数据分析师,了解业务、寻找数据、讲解报告,都需要和不同部门的人打交道,因此沟通能力很重要。 对于高级数据分析师,需要开始独立带项目,或者和产品做一些合作,因此除了沟通能力以外,还需要一些项目协调能力。 对于数据挖掘工程师,和人沟通技术方面内容偏多,业务方面相对少一些,对沟通协调的要求也相对低一些。
快速学习 无论做数据分析的哪个方向,初级还是高级,都需要有快速学习的能力,学业务逻辑、学行业知识、学技术工具、学分析框架……数据分析领域中有学不完的内容,需要大家有一颗时刻不忘学习的心。 以上,就是我对数据分析师能力的总结。 数据分析师的工具体系 一图说明问题 可以从图上看到,Python在数据分析中的泛用性相当之高,流程中的各个阶段都可以使用Python。所以作为数据分析师的你如果需要学习一门编程语言,那么强力推荐Python~ 以上,本期内容就讲完了。
转载请注明出处:http://blog.csdn.net/jevonscsdn/article/details/54353177 【Jevons’Blog】
ThreadLocal的目的和作用: 用于实现线程内的数据共享,即对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时又共享另外一份数据。 每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map增加一条记录,key就是ThreadLocal对象,而value就是各自线程通过set方法传进去的值。在线程结束时,可以调用ThreadLocal.clear()方法,这样会更快释放内存(非必调,因为线程结束后也可以自动释放相关的ThreadLocal变量)。
当我们需要使用到线程本地变量时,常常会想到ThreadLocal类,而每一个线程都各自维护着一个ThreadLocal.ThreadLocalMap映射表:
public class Thread implements Runnable { ... /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals= null; ... } 下面我们通过源代码分析Thread中持有变量threadLocals的初始化过程。
先来看一下初始化方法:
public class ThreadLocal<T> { ... void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); } ... } 可以看出该 createMap(Thread t, T firstValue)方法为Thread类中的threadLocals进行了初始化操作。
再追踪一下ThreadLocalMap的构造方法源码:
ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.
总是有那么一群人,闲的没事乱搞服务器!也不知道谁在暴力破解公司的ftp。
日志服务器不停报警,不停的用户密码尝试登陆ftp,倒不是担心你登陆,密码复杂性也够一段时间破解的。漏洞的话就要看攻击者的 道行了。关键是我担心的是我的日志服务器啊,要不停的记录这些东西。看着不舒服影响心情。
动态查看日志:(如果尝试比较多的ip可手动禁止访问,当然也可以写个ftp防止暴力破解脚本,如果尝试次数过多,iptables暂时封闭即可。)
查看ip,阿里云。逗我呢。也不知道谁躺枪了。估计连接vpn或者其它方式搞得!
先写个acl禁止再说。平静了。。。
反思:防火墙只允许公司连接ftp,这是什么鬼?公司也没有搭建vpn之类的东西。
难道局域网被入侵了?道行还不够,大家觉得呢?
要啃一些论文,先将一些概念搞清楚
令:A是命题,B是结论
必要性:A→B
充分性:B→A
A→B:A是B的充分条件
A成立B一定成立,A不成立B不一定不成立
B→A:A是B的必要条件
A成立B不一定成立,A不成立B一定不成立
A↔B:AB互为充要条件(充分必要),即B成立当且仅当A成立
转载于:https://www.cnblogs.com/acha/p/6263887.html
Part1:JSON格式的支持
版本终于支持了原生的JSON格式,即将关系型数据库和文档型NO_SQL数据库集于一身。本文接下来将对这特性分别就和各自实现的方法异同进行介绍和演示。
Part2:创建相应表结构
[root@HE3 ~]# mysql -V
mysql Ver Distrib , for linux- (x86_64) using EditLine wrapper
mysql> create database helei;
Query OK, 1 row affected ( sec)
mysql> use helei;
Database changed
mysql> create table helei (id int(10) unsigned NOT NULL,context json default null,primary key(id));
Query OK, 0 rows affected ( sec)
mysql> show create table helei \G
*************************** 1. row ***************************
Table: helei
Create Table: CREATE TABLE `helei` (
`id` int(10) unsigned NOT NULL,
`context` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set ( sec) Part3:构造数据&测试
问题描述 新装的CentOS 6.5 没有sz/rz命令,sz/rz工具包
解决办法 在CentOS命令行运行以下命令
yum install lrzsz 过程 [root@xxt downloads]# yum install lrzsz Loaded plugins: fastestmirror Determining fastest mirrors * base: mirrors.cqu.edu.cn * extras: mirrors.cqu.edu.cn * updates: mirrors.cqu.edu.cn base | 3.7 kB 00:00 extras | 3.3 kB 00:00 extras/primary_db | 30 kB 00:00 updates | 3.4 kB 00:00 updates/primary_db | 3.6 MB 00:00 Setting up Install Process Resolving Dependencies --> Running transaction check ---> Package lrzsz.i686 0:0.12.20-27.1.el6 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: lrzsz i686 0.
之前一直想有一个管理文献的好工具,但囿于麻烦都没有去做。
最近需要阅读大量的文献,便重新拾起了这个念头,在几经搜索后,选定了Zotero作为文献管理工具。
至于为什么选择这个软件,我也许并说不清,网上有很多对比评价的帖子,可以略加参考。
那到现在为止,我也使用了大半个月了,就来分享下Zotero的使用心得吧。
Zotero官网:https://www.zotero.org/
1. 下载安装Zotero
首先要指导Zotero是主要分为2个版本,其一是独立版本,其二是浏览器插件版本。先说浏览器插件版本,如果用的浏览器是firefox,那和Zotero兼容性最高,表现也最出色,具有和独立版本媲美的功能。如果是其他的浏览器,也可以选择下载。插件版本的优势在于可以直接在浏览器中进行右键或者点击相关按钮对网页进行条目建立,并下载其中的文献添加详细信息。虽然独立版本和浏览器插件版本是可以同时存在的,但由于Zotero的同步策略做的尚不完美,可能在同步的时候会出现小问题。所以选择版本的时候需要稍加斟酌。
由于Zotero服务器建立在国外,访问和下载时速度会受限。可以考虑通过百度搜索关键词下载,但有可能下载到的并不是最新版的。这个也没关系,可以通过自动更新解决。
假设现在下载好了Zotero安装包,安装过程很简单,没有需要特别注意的地方。如果之前下载的是旧版本,则可以通过Zotero程序的【帮助-检查更新】来自动安装最新的版本。如果更新过程比较慢,也没有关系,可以放心的点关闭,会在后台继续进行下载更新。
2. 配置Zotero
a) 同步设置
Zotero支持在线同步,可以在多个不同的终端进行访问自己的文献库,所以需要注册一个帐号。可以直接在官网注册完后,进入程序的【工具-首选项-同步】相关地方填入帐号密码进行同步。
对于插件版本的Zotero设置也类似。
b) 搜索设置(PDF索引)
这个设置非常重要,因为Zotero有个很强大的功能,可以在直接拖入PDF后,右键对其进行条目的自动创建(重新抓去PDF的元数据),尽管对某些来源的PDF并不是很好的支持,但也会方便很多。这个功能首先要得到一些PDF辅助程序的支持,这个在Zotero程序的【工具-首选项-搜索-PDF索引】下面可以确认安装状态,如果显示未安装,则点击检查更新就可以进行自动下载安装了。这里速度可能有点慢,多试几次就行~安装完了重新打开程序会显示下图界面。
c) 引用设置(参考文献插入)
这个也关系到一个很好用的功能,就是自动生成参考文献条目来插入到word或者latex中。进入到【工具-首选项-引用】确认word插件的安装状态,如果没有安装就点击重新安装即可。【样式】栏目下还可以对要导出的参考文献条目格式进行配置。
d) 数据存储位置设置
因为随着使用时间增长,文献库会日渐庞大,因此不建议直接使用默认的数据存储位置(C盘)。这个也可以在【工具-首选项-高级-文件和文件夹】栏目下进行修改,选择数据存储位置-自定义,然后选择目标目录即可。之后会提示你需要手动将Zotero原数据库下的文件移动到新目录下,这个很方便,可以直接点击打开数据文件夹,然后将里面的内容全部移动到目标文件夹下就可以了。
e) 其他设置
针对Zotero的其他设置,比如字体大小等,也可以在【工具-首选项-常规】下进行设置。
3. Zotero的使用
这里就介绍简单的使用方法,首先在左侧可以建立层次的目录文件夹。在每个目录下都可以添加条目,或者通过拖动PDF到中间空白处并右键抓去元数据来建立条目。如果PDF抓取元数据失败也没事,可以右键PDF选择建立父条目。在新建的条目右侧选中信息栏目,可以手动填入文献的相关信息,方便查阅。同时在空的条目下,也可以以添加附件的形式将PDF等格式的文件添入其中,这样以后双击该条目就可以直接打开PDF来查阅。
此外,Zotero还有很好用的笔记功能,在选中条目后,在右侧的笔记处可以添加任意数目的笔记条目来进行记录。
最后,要生成参考文献条目时,可以在Zotero文献目录下多选多个条目,右键-从选中条目建立引文目录,在弹出的窗口中设置预期的格式,并选择插入的方式(如剪贴板),然后就可以用复制的形式将引文直接复制到word的相应位置处。
这篇博客主要实现将so文件注入到进程中,并且在被注入的进程中执行so文件中的方法,先说下环境使用的是4.4的模拟器,嘻嘻.,参考 Android中的so注入(inject)和挂钩(hook) - For both x86 and arm ,我只是整合了这些资源,并将其run起来,感谢作者提供的文件和思路
先说下大概的实现思路吧:
创建so文件所在进程的应用,创建c文件,并使用ndk-build编译出可执行so文件创建执行so文件所在进程应用,创建c文件,在main方法中指定需要注入的进程,并执行第一步build出的so文件中的方法,并使用ndk-build编译出可执行命令,push进去手机,执行该命令即可下面会用到Android中ndk开发,如果有不熟悉的,可以参考我之前的博客Android NDK开发 ##创建编译可执行文件
首先创建一个应用hellodemo,用来编译出可执行文件(后面会将该文件注入到指定的进程),在hellodemo中创建jni目录,在该目录下创建hello.c文件,hello.c将用来编译生成可执行文件。
###hello.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <android/log.h> #include <elf.h> #include <fcntl.h> #define LOG_TAG "DEBUG" #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args) void hook_entry(char * a){ LOGD("Hook success, pid = %d\n", getpid()); while(1) { LOGD("Hello *********** %s\n", a); } } 可以看到在当前hello.c文件中,创建一个hook_entry方法,不断打印当前传入的字符串参数值
###创建Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog #LOCAL_ARM_MODE := arm LOCAL_MODULE := hello LOCAL_SRC_FILES := hello.
有时启动应用时会发现端口已经被占用,这时我们希望知道是哪个应用/进程在使用该端口,及如何kill它。 检查端口被哪个进程占用 netstat -lnp|grep 8000 8000请换为你需要的端口,如:80 如下图, 找到进程号:11100
查看进程的详细信息 ps 11100 杀掉进程 kill -9 11100 强制杀掉编号为11100的进程
Numpy是Python下一个非常强大的库。在这篇笔记里我将会把CS231n课程用到的一些Python和Numpy的用法用通俗易懂的语言和例子记录下来,方便自己复习也方便他人学习。这里附上Numpy的官方链接。
1.enumerate:不是单纯的打印内容,枚举的时候还会加上index
>>> classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] >>> for y, cls in enumerate(classes): ... print y, cls 0 plane 1 car 2 bird 3 cat 4 deer 5 dog 6 frog 7 horse 8 ship 9 truck 2.np.flatnonzero():打印非零元素的下标,具体如下 >>> x = np.arange(-2, 3) >>> x array([-2, -1, 0, 1, 2]) >>> np.flatnonzero(x) array([0, 1, 3, 4]) 3.numpy.random.randint(low, high=None, size=None, dtype='l'):打印[low,high)之间的整数;如果high没有定义,那么就从[0,low)
>>> np.
现在的手环都有消息提醒,那么手机端的app怎么写呢?如何才能获得不同app的消息提醒,不如微信,qq,短信,来电提醒,,,本人渣渣刚开始学习,什么都不会,求指点
初衷:为了完成端口映射,一开始以为电信光猫不支持自定义路由,因为通过useradmin登录进去后
没有找到对应的选项。一番了解之后,原来光猫有超级密码,电信装机时是不会告诉你的,电信客服
一般也不会告诉你的!
1、telnet 192.168.1.1
账号:root
密码:Zte521
2、输入命令:
sendcmd 1 DB p DevAuthInfo
得到管理员账号密码如下:
<DM name="User" val="telecomadmin"/>
<DM name="Pass" val="xxx"/>
3、[可选]禁用光猫中的TR069(不是删除TR069),杜绝运营商后台更新配置等检查信息。从而可以一直用telnet连接光猫。
sendcmd 1 DB p MgtServer
解释:查看一下当前的电信远程控制
sendcmd 1 DB set MgtServer 0 Tr069Enable 0
解释:禁用TR069远程控制
sendcmd 1 DB save
解释:修改保存
注:a. 我是在拔掉光纤之后,点击了恢复出厂设置,然后再做以上两步操作的。如若不然,telnet连接失败!
b. 参考1: http://www.cnblogs.com/dolphi/p/4309772.html
c. 参考2: https://www.chiphell.com/thread-1654145-1-1.html
d. 参考3: http://blog.sina.com.cn/s/blog_540316260102v2ru.html
另外,设置桥接模式的方法
我家路由器安装好之后被设置成了路由模式,也即自带路由的功能,光猫自动拨号,然后有线、无线自动获取ip地址。
我想要设置成桥接模式,也即光猫仅仅提供光纤网络信号,网络连接需要通过电脑或者路由器来拨号连接。
1. 用telecomadmin用户登录管理界面,删除路由模式的连接
2. 创建新的PPP连接,选择上网模式,然后选择桥接
3. 将路由器连接到光猫的某个网口,进入路由器的网络设置页面,设置拨号连接即可。
参考1: http://www.myxzy.com/post-344.html
转载于:https://www.cnblogs.com/xianzhon/p/6238350.html
问题:今天在写mybatis plugin插件的时候碰到如下错误:
org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession. ### Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 35; columnNumber: 17; 元素类型为 "configuration" 的内容必须匹配 "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"。 at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:82) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:66)分析:解析xml的plugins出现问题。 原因:Mybatis3.X 的版本使用的 dtd 作为 XML 的格式校验文档。 而在 XML 规范中,dtd 是有严格的顺序的,在报错的异常中已经列出了对应的顺序,所以必须进行严格匹配:plugins必须写在mappers之前。
<plugins> <plugin interceptor="com.steven.interceptor.PageInterceptor"> <property name="databaseType" value="mysql"/> </plugin> </plugins> <mappers> <mapper resource="mapper/Order.xml"/> <mapper resource="mapper/Workflow.xml"/> <mapper resource="mapper/PacificLog.xml"/> <mapper resource="mapper/OrderMapping.xml"/> <mapper resource="mapper/PacificAgreementInstance.xml"/> <mapper resource="mapper/PlatformRelation.xml"/> <mapper resource="mapper/PlatformRelationAttributes.xml"/> </mappers>参考:http://www.cnblogs.com/myssh/p/5404936.html
Java中线程的状态分为6种。
1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3. 阻塞(BLOCKED):表示线程阻塞于锁。
4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
6. 终止(TERMINATED):表示该线程已经执行完毕。
这6种状态定义在Thread类的State枚举中,可查看源码进行一一对应。
一、线程的状态图 二、状态详细说明 1. 初始状态(NEW) 实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。
2.1. 就绪状态(RUNNABLE之READY) 就绪状态只是说你资格运行,调度程序没有挑选到你,你就永远是就绪状态。调用线程的start()方法,此线程进入就绪状态。当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。锁池里的线程拿到对象锁后,进入就绪状态。 2.2. 运行中状态(RUNNABLE之RUNNING) 线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一的一种方式。
3. 阻塞状态(BLOCKED) 阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。
4. 等待(WAITING) 处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。
5. 超时等待(TIMED_WAITING) 处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。
6. 终止状态(TERMINATED) 当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。这个线程对象也许是活的,但是它已经不是一个单独执行的线程。线程一旦终止了,就不能复生。在一个终止的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。 三、等待队列 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) 代码段内。与等待队列相关的步骤和图 线程1获取对象A的锁,正在使用对象A。线程1调用对象A的wait()方法。线程1释放对象A的锁,并马上进入等待队列。锁池里面的对象争抢对象A的锁。线程5获得对象A的锁,进入synchronized块,使用对象A。线程5调用对象A的notifyAll()方法,唤醒所有线程,所有线程进入同步队列。若线程5调用对象A的notify()方法,则唤醒一个线程,不知道会唤醒谁,被唤醒的那个线程进入同步队列。notifyAll()方法所在synchronized结束,线程5释放对象A的锁。同步队列的线程争抢对象锁,但线程1什么时候能抢到就不知道了。 四、同步队列状态 当前线程想调用对象A的同步方法时,发现对象A的锁被别的线程占有,此时当前线程进入同步队列。简言之,同步队列里面放的都是想争夺对象锁的线程。当一个线程1被另外一个线程2唤醒时,1线程进入同步队列,去争夺对象锁。同步队列是在同步的环境下才有的概念,一个对象对应一个同步队列。线程等待时间到了或被notify/notifyAll唤醒后,会进入同步队列竞争锁,如果获得锁,进入RUNNABLE状态,否则进入BLOCKED状态等待获取锁。 五、几个方法的比较 Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态。作用:给其它线程执行机会的最佳方式。Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。thread.join()/thread.join(long millis),当前线程里调用其它线程t的join方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁。线程t执行完毕或者millis时间到,当前线程一般情况下进入RUNNABLE状态,也有可能进入BLOCKED状态(因为join是基于wait实现的)。obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout) timeout时间到自动唤醒。obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。LockSupport.park()/LockSupport.parkNanos(long nanos),LockSupport.parkUntil(long deadlines), 当前线程进入WAITING/TIMED_WAITING状态。对比wait方法,不需要获得锁就可以让线程进入WAITING/TIMED_WAITING状态,需要通过LockSupport.unpark(Thread thread)唤醒。 六、疑问 等待队列里许许多多的线程都wait()在一个对象上,此时某一线程调用了对象的notify()方法,那唤醒的到底是哪个线程?随机?队列FIFO?or sth else?Java文档就简单的写了句:选择是任意性的(The choice is arbitrary and occurs at the discretion of the implementation)。
一、设置Eclipse打开时自动弹出选择默认工作空间的提示
注意上图工作空间处没有编辑或添加功能,是一个小小的不足,所以,我们变通一下,打勾提示,这样我们在关闭eclipse软件后再打开时,再设置新的工作空间了。
二、再重新打开eclipse时设置新的工作空间的路径
查看Android设备的CPU架构信息,可以使用命令来完成:
1、adb shell 2、cat /proc/cpuinfo ➜ ~ adb shell shell@hennessy:/ $ cat /proc/cpuinfo Processor : AArch64 Processor rev 2 (aarch64) //cpu架构 processor : 0 BogoMIPS : 26.00 //核心数 Features : fp asimd aes pmull sha1 sha2 crc32 CPU implementer : 0x41 CPU architecture: AArch64 CPU variant : 0x0 CPU part : 0xd03 CPU revision : 2 Hardware : MT6795 //品牌 shell@hennessy:/ $ AArch64是ARMv8 架构的一种执行状态。
为了更广泛地向企业领域推进,需要引入 64 位构架。同时也需要在 ARMv8 架构中引入新的 AArch64 执行状态。AArch64 不是一个单纯的 32 位 ARM 构架扩展,而是 ARMv8 内全新的构架,完全使用全新的 A64 指令集。这些都源自于多年对现代构架设计的深入研究。更重要的是, AArch64 作为一个分离出的执行状态,意味着一些未来的处理器可能不支持旧的 AArch32 执行状态。 虽然最初的 64 位 ARM 处理器将会完全向后兼容,但我们大胆且前瞻性地将 AArch64 作为在 ARMv8 处理器中唯一的执行状态。我们在这些系统中将不支持 32 位执行状态, 这将使许多有益的实现得到权衡,如默认情况下,使用一个较大的 64K 大小的页面,并会使得纯净的 64 位 ARM 服务器系统不受遗留代码的影响。立即进行这种划分是很重要的,因为有可能在未来几年内将出现仅支持 64 位的服务器系统。没有必要在新的 64 位架构中去实现一个完整的 32 位流水线,这将会提高未来 ARM 服务器系统的能效。这样回想起来, AArch64 作为在 Fedora ARM 项目中被支持的 ARM 构架是一个很自然的过程: armv5tel、armv7hl、aarch64。新的架构被命名为:aarch64,这同 ARM 自己选择的主线命名方式保持一致,同时也考虑到了 ARM 架构名与 ARM 商标分开的期望。
学了好长时间的java对于java中的对象一直没有理清楚,今天楼主对java中的对象进行了整理,希望对大家有帮助。
理解和使用java中的对象,我们首先了解一下构造方法与对象的创建。 类是面向对象语言中最重要的一种数据,可以用类声明变量。面向对象语言中,用类声明的变量称为对象。
和基本数据类型不同,在声明对象后,还必须创建对象,即为声明的对象分配所拥有的的变量(确定对象所具有的属性),当时使用一个类创建一个对象时,也叫给出了这个类的一个实例。通俗的讲,类是创建对象的模板。
1. 构造方法 构造方法是类中的一种特殊方法,用类创建对象时需要使用它的构造方法,类中的构造方法必须和它所在类的名字完全相同,且没有类型。 class Person { int age; String name; Person(){ } } 在Person类中Person()是一个构造函数,其实这个方法是被java隐藏的,也就是说如果类中没有编写构造方法,系统会默认该类有一个无参数,且方法体中没有语句的构造函数。如Person类中的Person(){ },如果类里定义了一个或多个构造函数,那么java就不提供默认的构造方法了。如下: class Person { int age; String name; Person(){ age=22; name="刘德华"; } Person(int age,Stirng name){ System.out.println("the man age is"+age+"name: "+name); } } 2 创建对象 (1)对象声明 一般格式为: 类的名字 对象的名字; 如: Person person; (2)为声明的对象分配变量 1.使用new运算符和类的默认构造方法为声明的对象分配变量,即创建对象。 class Person { int age; String name; void speak(String name){ System.out.println(name); } } public class OuXiang { public static void main(String[] args) { Person liudehua; //声明对象 liudehua=new Person(); //为变量分配变量(使用new和默认的构造方法) } } 2.
Fix协议,有现成的QuickFix,拿来就可以用,不过要上手也要了解一下FIX协议,入手:
settings_ = new FIX::SessionSettings(p.string()); store_factory_ = new FIX::FileStoreFactory(*settings_); log_factory_ = new FIX::FileLogFactory(*settings_); initiator_ = new FIX::SocketInitiator(*this, *store_factory_, *settings_, *log_factory_); initiator_->start(); 因为是客户端,所以要用Initialtor,服务端的话要用Acceptor
这里要加载配置文件:
[DEFAULT] ConnectionType=initiator ReconnectInterval=60 SenderCompID=xxxxxxxxx TargetCompID=xxxxxxx FileLogPath=log FileStorePath=log [SESSION] BeginString=FIX.4.2 StartTime=01:00:00 EndTime=23:59:00 HeartBtInt=30 SocketConnectPort=xxx SocketConnectHost=xxx.xxx.xxx.xxx DataDictionary=FIX/FIX42.xml ValidateUserDefinedFields=N 配置要注意两个log文件的配置要写在【default】下。不然老出现找不到的异常。 具体的字段可以看说明文档
下面是goods_information.json文件的内容,它包含的就是简单的JSON串:
[{"classification":"饮料","name":"可口可乐","price":"3","unit":"瓶"},
{"classification":"饮料","name":"雪碧","price":"3","unit":"瓶"},
{"classification":"水果","name":"苹果","price":"5.5","unit":"斤"},
{"classification":"水果","name":"荔枝","price":"15","unit":"斤"},
{"classification":"生活用品","name":"电池","price":"2","unit":"个"},
{"classification":"食品","name":"方便面","price":"4.5","unit":"袋"}] 注意:对象的属性名必须使用双引号
使用$http.get方法获取JSON文件
<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en" >
<meta charset="UTF-8">
<title>demo</title>
<script src="../js/angular.min.js"></script>
</head>
<body ng-controller="demoCtrl">
<table>
<tr ng-repeat="item in goods_informations">
<td>{{item.classification}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.unit}}</td>
</tr>
</table>
<script>
var app=angular.module('myApp',[])
app.controller('demoCtrl', function($scope,$http) {
$http.get('../js/goods_information.json').success(function(data){
$scope.goods_informations = data;
})
})
</script>
</body>
</html>
打开需要引用的项目的pom文件,每个pom文件都有如下一段节点:
<modelVersion>4.0.0</modelVersion>
<groupId></groupId>
<artifactId></artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Maven_Project Maven Webapp</name>
<url>http://maven.apache.org</url>
其中
<groupId></groupId> <artifactId></artifactId> <version></version> 这三个是需要用到的,需要复制下来
然后在自己的pom文件中的<dependencies>节点里添加<dependency>节点,在<dependency>里添加刚才复制的
<groupId></groupId> <artifactId></artifactId> <version></version>
最后在项目右键菜单里选择Maven的update project从新构建一下项目就可以成功的引用到项目了
JSONObject 转对象:
JSONObject data = (JSONObject) str;
obj = JSONObject.parseObject(data.toString(), Object.class);
JSONArray转List:
JSONArray array = data.getJSONArray("节点名称"); List<Object> ObjectList = JSON.parseArray(array.toJSONString(), Object.class);
1.选择建立Meaven Project项目 2.在列表里的Artifact Id里找到meaven-archetype-webapp 3.填写组名(Group Id)、组件名(Artifact Id) 4.引入Spring依赖包:在pom文件中引入以下特性 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${srping.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${srping.version}</version> </dependency> 这样我们就建立了一个MeavenWeb项目,但是建立后会出现各种报错,下面介绍一下常见报错的解决: 1.
这个主要介绍的方法是获取命令的输出内容,而不是命令执行成功与否的返回值。
通常情况下,在shell脚本中需要获取命令的输出内容,然后根据输出内容判断下一步的执行操作。
比较常用的一种方式就是, 匹配命令输出的内容中是否存在某些关键字,选择执行的不同动作。
比较常用的一种方式就是采用反向单引号的方式 -- 保存结果的变量名=`需要执行的linux命令`
这种方式在使用时,有些细节的地方需要注意。 先用几个例子来说明一下。
比如在CentOS7环境中,使用rpm -qa命令查询某些rpm包是否安装,没有安装的话进行安装操作。
举个简单的例子来说:
#!/bin/bash
check_results=`rpm -qa | grep "zlib"`
echo "command(rpm -qa) results are: $check_results"
if [[ $check_results =~ "zlib" ]] then echo "package zlib has already installed. "
else echo "This is going to install package zlib"
fi
保存为test.sh文件,然后运行
$bash test.sh 结果为:
command(rpm -qa) results are: zlib-1.2.7-13.el7.x86_64
package zlib has already installed. 这个脚本基本上是可以工作的。
那么,我们同样使用类似的方式来检查iscsi-initiator软件包是否安装。 与上一个命令不同的是,这个命令是否安装不能通过rpm -qa命令获取。
我们采取另一种方式
#!/bin/bash
check_results=`iscsiadm --version | grep iscsiadm`
本人使用的是webstorm2016 2.3版本,结果竟然不支持vue文件,于是经过查找找到了一个方法,亲测可用,非常简单哦。
前言 在为移动端做API接口时,Java服务器端对接口一般需要做两种处理。
1.对请求的接口在interceptor 做authorize鉴权
2.对请求过来的参数进行加密校验,防止参数在传递过程中被篡改。
鉴权 鉴权方式我所使用的到的基本上目前有以下三种: 1.session
2.cookie
3.oauth2.0
对于这三种方式,以后细讲下。在此不再多说。
加密 对于传输过程中防止参数被篡改,可以使用HTTPS来有效的增强安全性。
对于重要的数据传输,除了需要https来认证,还需要对传入参数进行加密解密的校验,达到双层保证。
一般处理思路:
将传入参数组合成字符串,然后做加密,得到加密的token值;调用接口时,同时将此值传入。服务器拿到此值,根据对应的加密方式解密比对。
来验证传入值的完整性。
关于加密方式,这里不再赘述。可根据接口的重要程度来选择。
如哈希算法md5、对称加密的DES、非对称的RSA或者一些加盐加密。
以md5为例,使用Java的SortedMap,对请求参数进行MD5,并传入。
SortedMap<Object, Object> requestParams = new TreeMap<Object, Object>(); requestParams.put("version", "1"); requestParams.put("userName", "123456"); requestParams.put("password", "123456"); StringBuffer requestParamsStringBuffer = new StringBuffer(); System.out.println("排序之后的Key Value:"); for (Map.Entry<Object, Object> entry : requestParams.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); requestParamsStringBuffer.append(entry.getKey() + "" + entry.getValue()); } System.out.println(requestParamsStringBuffer.toString()); String md5=""; try { md5 = MD5.getMd5(requestParamsStringBuffer.toString()); } catch (NoSuchAlgorithmException e) { e.
JDBC学习(三)
在知道怎么完成与Mysql数据库链接操作和提交SQL到Mysql数据库以后,还需要知道怎么从Mysql数据库获取信息。
接口 ResultSet ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。
SQL返回的表格信息按列表的形式被封装在ResultSet中。通过遍历可以将其获取。
//通过遍历ResultSet对象,获取表格信息。
public class Demo1 {
private static List<Book> listBook3()throws Exception{
List<Book> booklist = new ArrayList<Book>();
Connection con = DbUtil.getConnection();
System.out.println("获取链接成功....");
String sql="select *from t_book";
PreparedStatement pre = con.prepareStatement(sql);
System.out.println("获取SQL预编译对象成功.....");
ResultSet rs = pre.executeQuery();
System.out.println("获取数据库表ResultSet接口对象成功.....");
System.out.println("开始遍历....");
while(rs.next()){
int id = rs.getInt("id"); String bookName = rs.getString("bookName");
float price = rs.getFloat("price");
String author = rs.getString("author");
int bookType = rs.getInt("bookTypeId");
转义字符含义\\反斜杠\a警报,响铃\b退格(删除键)\f换页(FF),将当前位置移到下页开头\n换行\r回车\t水平制表符(tab键) \v垂直制表符 vim test4.sh
#!/bin/bash v1="Spark" v2="Scala" echo -e "First is $v1; \nSecond is $v2;" # -e 表示对转义字符进行替换。 echo "###############" echo "First is $v1; \nSecond is $v2;" # 不使用 -e 选项,将会原样输出 echo "-------------" cmd=`df | grep Filesystem;date` # 将输出结果暂时保存 echo "Cmd is $cmd" $ sh test4.sh
First is Spark; Second is Scala;
###############
First is Spark; \nSecond is Scala;
-------------
Cmd is Filesystem 1K-blocks Used Available Use% Mounted on
http://blog.csdn.net/lincyang/article/details/44418379
场景: 朋友看见你Android手机中的游戏或应用很好玩,也想装一个此程序,但限于网络条件不能从网上下载。那么最简单的办法就是直接从你手机中将此apk扣出来给他安装上。
pm命令 第一步,找到程序的包名 借助adb shell pm命令,将安装的所有应用包名列出来:
$ adb shell pm list packages package:android package:cn.wps.moffice package:com.android.backupconfirm package:com.android.bluetooth package:com.android.browser package:com.android.calculator2 package:com.android.camera package:com.android.certinstaller package:com.android.contacts 1234567891011 1234567891011 第二步,找到apk的位置
$ adb shell pm path com.tence01.mm package:/data/app/com.tence01.mm-1.apk 12 12 第三步,pull出来
$ adb pull /data/app/com.tence01.mm-1.apk ~/apks 2407 KB/s (25567735 bytes in 10.370s) 123 123 root的手机会更好办 $ adb shell shell@android:/ $ su shell@android:/ # cd data/app shell@android:/data/app # ls com.android.update.dmp-2.apk com.baidu.superservice-1.apk com.tence01.mm-1.apk com.tencent.mm-1.apk 123456789 123456789 或者直接搜索你要的apk:
打开cmd进入mysql所在盘,进入mysql文件夹,即输入cd mysql,再进入bin文件夹,即输入cd bin,最后输入mysql -uroot -proot ,如图所示:
我这样就解决闪退问题并成功进入mysql了。
另外,您也可以去http://www.wampserver.com/上下载wampserver,里面包含了Apache+Mysql+PHP,同样也可以使用mysql。
首先选中同时代码,按tab键,右移,如果要左移,按shift+tab键。
一 引言 flask中具有四种钩子被做成了修饰器,我们在后端可以进行调用做相关的操作.使用钩子函数时,我们需要借助flask的全局变量g.g作为中间变量,在钩子函数和视图函数中间传递数据.我们先引入全局变量g
from flask import g 然后注册一个视图函数,用来显示g中的数据
@app.route('/test') def test(): return g.string 二 before_first_request 注册一个函数,在处理第一个请求之前运行.
@app.before_first_request def bf_first_request(): g.string = 'before_first_request' 运行程序,调用http://localhost:5000/test会显示g中传递的string变量 三 before_request 注册一个函数,在处理每次请求之前运行.
@app.before_request def bf_request(): g.string = 'before_request' 四 after_request 注册一个函数,在每次请求之后运行.注册的函数至少需要含有一个参数,这个参数实际上为服务器的响应,且函数中需要返回这个响应参数.
@app.after_request def af_request(param): return param 五 teardown_request 注册一个函数,同样在每次请求之后运行.注册的函数至少需要含有一个参数,这个参数实际上为服务器的响应,且函数中需要返回这个响应参数.
@app.teardown_request def td_request(param): return param Github位置:
https://github.com/HymanLiuTS/flaskTs
克隆本项目: git clone git@github.com:HymanLiuTS/flaskTs.git 获取本文源代码: git checkout FL15
最近项目使用Git管理,本文记录常用的Git命令。
cd到存放源代码的目录
1. git clone ***** // clone源代码
2. git pull // 更新源代码
3. git status // 查看源文件的状态(是否增删改)
4. git add .(filename) // 将修改增加
5. git commit -m "*****" // 预提交文件的改动
6. git push // 提交
7. git branch // 查看git的分支
8. git checkout dev(test/master) // 切换git分支
9. git merge test // 将test中的变动merge到当前分支
10.git diff filename // 查看文件的修改内容
如何撤销对文件的修改等等更多操作,等用到的时候在去查。
使用命令,工作效率提高了不少。
PLSQL Developer(安装、连接、汉化、注册图文教程) 一、安装 PLSQL Developer ---版本11.0.5.1790(64bit) 1、解压oracle客户端 到 d盘某个目录。 2、安装PLSQL Developer 开发工具,点击plsqlev1105.exe,开始进入安装界面,点击Next。
3、同意协议,Next。
4、选择自己的安装目录,Next。
5、选择自己安装的版本,默认传统安装,Next。
6、Install,进入安装进程。
7、finish。
二、进入PLSQL Developer
1、输入已安装的oracle数据用户及密码,数据库选择ORACLE,Normal权限。
2、可以看到连接成功并且界面为英文版工具栏。
三、汉化PLSQL Developer
1、点击language_zh_x86_64.exe,开始汉化,确定。
2、自动检测安装目录,只需点击蓝色向右箭头图标,表示进入下一步。
3、默认,蓝色下一步。
4、默认,蓝色下一步。
4、完成汉化,点击右下勾图标。
5、进入界面,可以看见汉化成功。
四、注册PLSQL Developer 1、点击帮助,选择注册。 2、输入产品代号、序列号、密码,点注册。
3、注册成功。
4、点击关于查看软件信息,至此完成安装、连接oracle数据库、汉化和注册所有步骤。
这篇文章中说明存在的问题最新的版本中已经解决,但是推荐看下vip的概念,为啥replics>1的时候,各个容器能通过访问一个服务名实现负载均衡。http://tonybai.com/2016/10/11/some-problems-under-swarm-mode-in-docker-1-12/
1.常量指针与指针常量 常量指针是针对于普通指针而言,语义在于指向常量的指针; 定义: const *<_name>; 常量指针解引用无法对引用值进行改变,但是可以改变指针自己的值; example: int tmp = 0, tmp2 = 1; const int *p = &tmp; p = &tmp2; // ok *p = 1;//error 指针常量语义指针本身为常量;解引用可以改变指向的值,但是不能改变指针本身的值: * const <_name>; example: int tmp = 0, tmp2 = 1; int* const p = &tmp; p = &tmp2; // error *p = 1;//ok typedef 与const 关于const有个地方特别容易出问题: 如下: typedef int* int_p; const int_p tmp; 这里的 tmp 到底是常量指针还是指针常量?一般的人会将typedef 直接替换那就理解为:const int_p tmp 与 const int* tmp相对应,其实这种理解是错的!!! 这里定义其实是一个指针常量;解释如下: typedef的意义在于定义一个类型,也就是是int_p 并不是直接被int* 替换,const语义在于对于定义的类型为常量,所以这里语义上解释为指针常量,指针本身是常量。
在ISE14.7 中双击启动modelsim仿真后,出现如下报错:
ERROR: Platform mismatch!
ERROR: Error(s) encountered while extracting pre-compiled simulation library information.
原因 :当前工程是用32bit ISE14.7版本打开,而modelsim是64bit版本,版本不匹配导致;
解决方法 :使用64bit 的ISE14.7 打开工程
贪心算法(又称贪婪算法)是指,在对 问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部 最优解。 所以不能保证最后结果是最优的,只能保证是比较优秀的,但是贪心算法的效率高. tsp 问题, 旅行商问题 ,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。 简介完了,说下思路. 就是不考虑远方,只考虑下一步, "今朝有酒今朝醉" , 只有保证下一步是最近的距离即可 . 要找到最近的下一步,首先需要把已经出现过的城市排除 , s[]记录了访问过的城市列表,遍历这个列表,访问过返回YES,没访问返回NO. // 这个城市k是否出现过了 bool isShowed(int k) { for (int i = 0; i < cityNum ; i++) { if (s[i] == k) { return YES ; } } return NO; } 找了未访问的城市,还需要找出这些未访问城市中最短的距离. distance是一个二维数组,存放了 i, j 城市间的距离, distance [i][ s [currentCity]] 表示第i个城市 和 当前访问城市间的距离 .i 不断增加,遍历了所有的城市,就可以找到最短距离了. void clostCityDistance(int currentCity) { // 距离当前城市最近的下一个城市 int tempClosest = 9999; for (int i = 0; i < cityNum; i++) { if ( isShowed(i) == NO && distance[i][s[currentCity]] <tempClosest ) { tempClosest = distance[i][s[currentCity]] ; s[currentCity+1] = i ; } } // 判断是否应该结束了, 如果s[]中有一个还是初始值-1的话,说明不该结束,继续寻找下一个城市.