2Sum_continue

凭着记忆写一下hashmap的写法:

  • 其实已经是修改过几个小毛病的版本, 比如new HashMap;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            int[] result = new int[2];
            Map map = new HashMap<Integer, Integer>();
            int i = 0;
            int j = numbers.length - 1;
            while(i <= j){
                if(!map.containsKey(numbers[j])){
                    map.put(target - numbers[i], numbers[i]);
                    i++;
                    j--;
                }else{
                    result[0] = i + 1;
                    result[1] = j + 1;
                    return result;
                }
            }
            
            return result;
        }
    }
    
  • Result:

    1
    2
    3
    4
    5
    
    Submission Result: Wrong Answer
    
    Input:	[3,2,4], 6
    Output:	0, 0
    Expected:	2, 3
    
  • 调整一下i和j的变更条件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            int[] result = new int[2];
            Map map = new HashMap<Integer, Integer>();
            int i = 0;
            int j = numbers.length - 1;
            while(i <= j){
                while(j > 0){
                    if(!map.containsKey(numbers[j])){
                        map.put(target - numbers[i], numbers[i]);
                        i++;
                    }else{
                        result[0] = i + 1;
                        result[1] = j + 1;
                        return result;
                    }
                    j--;
                }
            }
            
            return result;
        }
    }
    
  • Result:

    1
    2
    3
    4
    5
    
    Submission Result: Wrong Answer
    
    Input:	[3,2,4], 6
    Output:	0, 0
    Expected:	2, 3
    
  • 分析: 理论上之前本方法的时间复杂度是O(n^2); 如果按照上面写法两个while循环钱淘的话, 依然还是O(n^2), 这样就没意义了, 应该扫一遍数据进hashtable就可以判断出是否有结果了, 上面的问题就是怎样在得到两个相加和为target的数值之后取得他们的index,

何不在扫入hashmap的时候把index作为value存入呢? 这有点茅塞顿开的意思, 但是悲剧的是依然写错了..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] result = new int[2];
        Map map = new HashMap<Integer, Integer>();
        int i = 0;
        int j = 0;
        while(i < numbers.length){
            if(!map.containsKey(numbers[i])){
                map.put(target - numbers[i], i);
                i++;
            }else{
                j = map.get(target - numbers[i]);
                if(i < map.get(target - numbers[i])){
                    result[0] = i + 1;
                    result[1] = map.get(target - numbers[i] + 1);
                    return result;
                }else{ 
                    result[0] = j + 1;
                    result[1] = i + 1;
                    return result;
                }
            }
        }
        return result;
    }
}
  • Result:

    1
    2
    3
    
    Submission Result: Compile Error
    
    Line 12: error: incompatible types
    
  • 借助于eclipse debug, 终于找到问题所在, 应该去get(numbers[i]), 另外不加(Integer) leetcode无法贬编译 + 这个运算符, 其实我已经定义了get出来的是Integer, 按理说不用转换, 不知道为什么, 可能这样更严谨?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] result = new int[2];
        Map map = new HashMap<Integer, Integer>();
        int i = 0;
        while(i < numbers.length){
            if(!map.containsKey(numbers[i])){
                map.put(target - numbers[i], i);
                i++;
            }else{
                result[0] = (Integer)map.get( numbers[i]) + 1;
                result[1] = i + 1;
                return result;
            }

        }
        return result;
    }
}

总结: 自己想出来的和之前参考的solution虽然大致思路一样, 但是具体的实现上还是不同的, 而且貌似自己写的更简洁一些. 最后实在找不到问题所在了去看了下之前的solution, 发现那边也是直接map.get( numbers[i]), 并没有加强制类型转换. 不过加上肯定不会错就是了.

LeetCode:TwoSum (1)

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9 Output: index1=1, index2=2

OJ:

  • 首先用最笨的方法来解,不过好像Java Array的相关method我都忘得差不多了....记录下来再更正吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] result = new int[2]; 
        int l = numbers.size();
        int i, j;
        for (i = 0; i < l; i++){
            for(int j = i + 1; j < l; j++){
                if(numbers[i] + numbers[j] = target){
                    result[0] = i;
                    result[1] = j;
                    return result;
                }
            }
        }
        
    }
}
  • Result: Line4: error: cannot find symbol: method size()
  • 忘记有没有直接看Array长度的函数了,先不去查文档,转化成熟悉的String来做

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            String source  = numbers.toString();
            int[] result = new int[2]; 
            //int l = numbers.size();
            l = source.length();
            int i, j;
            for (i = 0; i < l; i++){
                for(int j = i + 1; j < l; j++){
                    if(numbers[i] + numbers[j] = target){
                        result[0] = i;
                        result[1] = j;
                        return result;
                    }
                }
            }
            
        }
    }
    
  • Result: Line 6: error: cannot find symbol: variable l 这个错误就是粗心大意了, 后面还有一个错误: Line 9: error: variable j is already defined in method twoSum(int[],int) 我还是再看一遍code再提交吧

  • 审查了一遍,又发现个错误, i的边界判定不应该是length, 而应该是length - 1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            String source  = numbers.toString();
            int[] result = new int[2]; 
            int l = source.length();
            int i, j;
            for (i = 0; i < l - 1; i++){
                for(j = i + 1; j < l; j++){
                    if(numbers[i] + numbers[j] = target){
                        result[0] = i;
                        result[1] = j;
                        return result;
                    }
                }
            }
            
        }
    }
    
  • Result: Line 9: error: unexpected type

  • 太不严谨了 - -, 平常用eclipse确实有依赖性, 函数名自己都不去记了, 这种 "==" 自己居然也没注意到

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            String source  = numbers.toString();
            int[] result = new int[2]; 
            int l = source.length();
            int i, j;
            for (i = 0; i < l - 1; i++){
                for(j = i + 1; j < l; j++){
                    if(numbers[i] + numbers[j] == target){
                        result[0] = i;
                        result[1] = j;
                        return result;
                    }
                }
            }
            
        }
    }
    
  • Result: Line 17: error: missing return statement

  • 简直是错误百出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            String source  = numbers.toString();
            int[] result = new int[2]; 
            int l = source.length();
            int i, j;
            for (i = 0; i < l - 1; i++){
                for(j = i + 1; j < l; j++){
                    if(numbers[i] + numbers[j] == target){
                        result[0] = i;
                        result[1] = j;
                        return result;
                    }
                }
            }
            
            return result;
            
        }
    }
    
  • Result: Runtime Error Message: Line 9: java.lang.ArrayIndexOutOfBoundsException: 3 Last executed input: [3,2,4], 6

  • 再改!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            String source  = numbers.toString();
            int[] result = new int[2]; 
            int l = source.length();
            int i, j;
            for (i = 0; i <= l - 2; i++){
                for(j = i + 1; j <= l - 1; j++){
                    if(numbers[i] + numbers[j] == target){
                        result[0] = i + 1;
                        result[1] = j + 1;
                        return result;
                    }
                }
            }
            
            return result;
            
        }
    }
    
  • Result: Runtime Error Message: Line 9: java.lang.ArrayIndexOutOfBoundsException: 3 Last executed input: [3,2,4], 6

  • IMPORTANT: 之所以会这样, 是因为Arrays.toString(), 并不是返回的Arrays里面元素的值, 比如 int[] numbers = {3, 2, 4}, 实测 System.out.println(numbers.toString()) 结果为 [I@53281264 所以上面code中的length实际为11, 怪不得会出现ArrayIndexOutOfBoundsException.

正确获得Arrays长度的方法: Arrays.length

之前刷提的时候不知所以然, 这次我们进阶了, 其实刚才写代码的时候也想到直接用 Arrays.length, 但是这个 .length不是一个method呀, 这在一切皆是Object的Java中显得有些不合群, 所以没用, 这次问题的出现是必然的, 因为我没有系统的学习过数据结构也好, 算法也好, Java也好, 以点带面, 查缺补漏吧.

还是参考StackOverflow的解释: 为什么ArrayList可以用ArrayList.size()来获取ArrayList的长度, 而 Array.length -- 并不是一个method, 却可以得到Array的长度呢?

Arrays are special objects in java, they have a simple attribute named length which is final. There is no "class definition" of an array (you can't find it in any .class file), they're a part of the language itself.

10.7. Array Members

The members of an array type are all of the following: The public final field length, which contains the number of components of the array. length may be positive or zero. The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[]. A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared. All the members inherited from class Object; the only method of Object that is not inherited is its clone method. Note also that ArrayList.size() provides the number of object actually stored in the array whereas myArray.length ([]) provides the "capacity". That is, if for myArray = new int[10];, it returns 10. It is not the number of objects you've put in the array.

  • 改正Arrays.length :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            String source  = numbers.toString();
            int[] result = new int[2]; 
            // int l = source.length();
            int l = numbers.length;
            int i, j;
            for (i = 0; i <= l - 2; i++){
                for(j = i + 1; j <= l - 1; j++){
                    if(numbers[i] + numbers[j] == target){
                        result[0] = i + 1;
                        result[1] = j + 1;
                        return result;
                    }
                }
            }
            
            return result;
            
        }
    }
    
  • 改正这一错误之后的代码可以正确运行了, 但是 leetcode的OJ表示此程序太慢了, Time Limit Exceeded.

这并不出乎意料, 因为这个是最笨的方法, 时间复杂度应该是O(n^2)

tcp和udp的不同

转载自:http://www.diffen.com/difference/TCP_vs_UDP

There are two types of Internet Protocol (IP) traffic. They are TCP or Transmission Control Protocol and UDP or User Datagram Protocol. TCP is connection oriented = once a connection is established, data can be sent bidirectional. UDP is a simpler, connectionless Internet protocol. Multiple messages are sent as packets in chunks using UDP.

Differences List

  • Connection:

    • TCP is a connection-oriented protocol.
    • UDP is a connectionless protocol.
  • Functions:

    • As a message makes its way across the internet from one computer to another. This is connection based.
    • UDP is also a protocol used in message transport or transfer. This is not connection based which means that one program can send a load of packets to another and that would be the end of the relationship.
  • Usage:

    • TCP is suited for applications that require high reliability, and transmission time is relatively less critical.
    • UDP is suitable for applications that need fast, efficient transmission, such as games. UDP's stateless nature is also useful for servers that answer small queries from huge numbers of clients.
  • Examples:

    • TCP: HTTP, HTTPs, FTP, SMTP, Telnet
    • UDP: DNS, DHCP, TFTP, SNMP, RIP, VOIP
  • Ordering of data packets

    • TCP rearranges data packets in the order specified.
    • UDP has no inherent order as all packets are independent of each other. If ordering is required, it has to be managed by the application layer.
  • Speed of transfer

    • TCP is slower that UDP
    • UDP is faster because there is no error-checking for packets.
  • Reliability

    • There is absolute guarantee that the data transferred remains intact and arrives in the same order in which it was sent.
    • There is no guarantee that the messages or packets sent would reach at all.
  • Header Size

    • TCP header size is 20 bytes.
    • UDP Header size is 8 bytes.
  • Common Header Fields

    • TCP: Source port, Destination port, Check Sum.
    • UDP: Source port, Destination port, Check Sum.
  • Streaming of Data

    • TCP: Data is read as a byte stream, no distinguishing indications are transmitted to signal message(segment) boundaries.
    • UDP: Packets are sent individually and are checked for integrity only if they arrive. Packets have definite boundaries which are honored upon receipt, meaning a read operation at the receiver socket will yield an entire message as it was originally sent.
  • Weight

    • TCP is heavy-weight. TCP requires three packets to set up a socket connection, before any user data can be sent. TCP handles reliability and congestion control.
    • UDP is lightweight. There is no ordering of messages, no tracking connections, etc. It is a small transport layer designed on top of IP.
  • Data Flow Control

    • TCP does flow control.
    • UDP does not have an option for flow control.
  • Error Checking

    • TCP does error checking
    • UDP does error checking too, but no recovery options.
  • Fields

    • TCP: 1.Sequence Number, 2.AcK number, 3.Data offset, 4.Reserved, 5.Control bit, 6,Window, 7.Urgent Pointer, 8.Options, 9.Padding, 10.Check Sum, 11.Source port, 12.Destination port
    • UDP: 1.Length,2.Source port, 3.Destination port, 4.Check Sum.
  • Acknowledgement

    • TCP: Acknowledgement segments
    • UDP: No Acknowledgement
  • Handshake

    • TCP: SYN, SYN-ACK, ACK
    • UDP: No handshake(connectionless protocol)
  • Checksum

    • TCP: checksum
    • UDP: to delete errors.

    Differences in Data Transfer Features

    TCP ensures a reliable and ordered delivery of a stream of bytes from user to server or vice versa. UDP is not dedicated to end to end connections and communication does not check readiness of receiver.

    Reliability

    TCP is more reliable since it manages message acknowledgment and retransmissions in case of lost parts. Thus there is absolutely no missing data. UDP does not ensure that communication has reached receiver since concepts of acknowledgment, time out and retransmission are not present.

    Ordering

    TCP transmissions are sent in a sequence and they are received in the same sequence. In the event of data segments arriving in wrong order, TCP reorders and delivers application. In the case of UDP, sent message sequence may not be maintained when it reaches receiving application. There is absolutely no way of predicting the order in which message will be received.

    Connection

    TCP is a heavy weight connection requiring three packets for a socket connection and handles congestion control and reliability. UDP is a lightweight transport layer designed atop an IP. There are no tracking connections or ordering of messages.

    Method of transfer

    TCP reads data as a byte stream and message is transmitted to segment boundaries. UDP messages are packets which are sent individually and on arrival are checked for their integrity. Packets have defined boundaries while ata stream has none.

    How TCP and UDP work

    A TCP connection is established via a three way handshake, which is a process of initiating and acknowledging a connection. Once the connection is established data transfer can begin. After transmission, the connection is terminated by closing of all established virtual circuits.

    UDP uses a simple transmission model without implicit hand-shaking dialogues for guaranteeing reliability, ordering, or data integrity. Thus, UDP provides an unreliable service datagrams may arrive out of order, appear duplicated, or go missing without notice. UDP assumes that error checking and correction is either not necessary or performed in the application, avoiding the overhead of such processing at the network interface level. Unlike TCP, UDP is compatible with packet broadcasts(sending to all on local network) and multicasting(seng to all subscribers).

    Different Applications of TCP and UDP

    Web browsing, email and file transfer are common applications that make use of TCP. TCP is used to control segment size, rate of data exchange, flow control and network congestion. TCP is preferred where error correction facilities are required at network interface level. UDP is largely used by time sensitive applications as well as by servers that answer small queries from huge number of clients. UDP is compatible with packet broadcast - sending to all on a network and multicasting - sending to all subscribers. UDP is commonly used in Domain Name System, Voice over IP, Trivial File Transfer Protocol and online games.

接上:拖拖拉拉

题外话:

本来预定下周一到的耳机今天(周六)中午就到了,听了一下感觉音效不错,但是也就那么回事,而且卡耳朵卡得有点紧,心想要不要退掉或者卖掉,点回去Amazon一看,已经是正常价140刀了,还是捡了个大便宜呀,可惜用老婆的号买第二个被Amazon cancel了,原因应该是两个账号用的信用卡卡号是一样的...这样理想计划买二卖一泡汤了...不要太贪心嘛

昨晚Larry请我去看电影,极品飞车,3D效果很爽,周五中午公司有披萨,结果一天没出办公室,屁股受不了,晚上本想回家的,下班太累,于是就给自己个借口去放松一下,结果错过老爸发来的Facetime,晚上11点半到家,打回去老爸问我干嘛去了,不想对老爸撒谎,如实说同事请看电影了,“咦也,你看人家”...羞愧难当

老父亲还卧病在床,不能在身边尽孝也抓紧时间做点正事吧!

接上篇,基础问题

threads and processes -- MultiThreading

Threads, of course, allow for multi-threading. A common example of the advantage of multithreading is the fact that you can have a word processor that prints a document using a background thread, but at the same time another thread is running that accepts user input, so that you can type up a new document. If we were dealing with an application that uses only one thread, then the application would only be able to do one thing at a time – so printing and responding to user input at the same time would not be possible in a single threaded application. Each process has it’s own address space, but the threads within the same process share that address space. Threads also share any other resources within that process. This means that it’s very easy to share data amongst threads, but it’s also easy for the threads to step on each other, which can lead to bad things. Multithreaded programs must be carefully programmed to prevent those bad things from happening. Sections of code that modify data structures shared by multiple threads are called critical sections. When a critical section is running in one thread it’s extremely important that no other thread be allowed into that critical section. This is called synchronization, which we wont get into any further over here. But, the point is that multithreading requires careful programming. Also, context switching between threads is generally less expensive than in processes. And finally, the overhead (the cost of communication) between threads is very low relative to processes.

SUMMARY

  1. Threads are easier to create than processes since they don't require a separate address space.

  2. Multithreading requires careful programming since threads share data strucures that should only be modified by one thread at a time. Unlike threads, processes don't share the same address space.

  3. Threads are considered lightweight because they use far less resources than processes.

  4. Processes are independent of each other. Threads, since they share the same address space are interdependent, so caution must be taken so that different threads don't step on each other.
    This is really another way of stating #2 above.

    1. A process can consist of multiple threads.

拖拖拉拉还是开始干正事吧

时间流水账:

7点半下班,7点45到家,没有做饭,随便吃吃蝴蝶酥+牛奶,到现在11点50,有4个小时的时间...看大酒神视频一个多小时,研究对比amazon上面thunderbolt转接线又不知过了多久,期间做了一点点正事就是把老婆要求的在职证明又重新扫描了一遍。 这种时间效率做什么都绝无成功之可能啊!

好了废话不多说,现在做一点有意义的事情。

正事

首先记录一下鹿牛的博客,老早就收藏了,但也没怎么看,以后要多向鹿牛学习。罗大佑的《追梦人》,真是好听。

找工作感觉没什么头绪,感觉算法课要重新学一遍,操作系统也要学,编译原理,设计模式,Spring, Hibernate,统统都要学。。。不过感觉比较实际的还是直接做题,大哥也是这样说。 另外找工群里面BT阿姨整理的资料包很好, 里面收录了一篇没怎么讲技术方面的东西,基本上是一些注意事项,读读也无妨,开卷有益嘛,摘录一点有用的东西:

记不记得俺提到过的experience里要用“吓人”的动词? 给你们一个小列表 (不是我的原创,不记得从哪儿抄来的了)。注意(1)全都是过去时; (2) 没有 studies, investigated, worked on, supported 这些无关痛痒的词。

  1. Accelerated 35. Empowered 69. Motivated
  2. Accomplished 36. Enabled 70. Negotiated
  3. Achieved 37. Encouraged 71. Obtained
  4. Acted 38. Engineered 72. Operated
  5. Adapted 39. Enhanced 73. Orchestrated
  6. Administered 40. Enlisted 74. Organized
  7. Allocated 41. Established 75. Originated
  8. Analyzed 42. Evaluated 76. Overhauled
  9. Approved 43. Examined 77. Oversaw
  10. Assembled 44. Executed 78. Performed
  11. Attained 45. Expedited 79. Pinpointed
  12. Boosted 46. Focused 80. Planned
  13. Budgeted 47. Forecasted 81. Prepared
  14. Built 48. Formulated 82. Prioritized
  15. Calculated 49. Founded 83. Processed
  16. Catalogued 50. Generated 84. Produced
  17. Chaired 51. Guided 85. Reconciled
  18. Coached 52. Harnessed 86. Repaired
  19. Collaborated 53. Identified 87. Researched
  20. Communicated 54. Illustrated 88. Revitalized
  21. Compiled 55. Implemented 89. Selected
  22. Consolidated 56. Improved 90. Solved
  23. Coordinated 57. Increased 91. Spearheaded
  24. Created 58. Initiated 92. Stimulated
  25. Cultivated 59. Instituted 93. Strengthened
  26. Decreased 60. Integrated 94. Succeeded
  27. Demonstrated 61. Introduced 95. Surpassed
  28. Designed 62. Invented 96. Synergized
  29. Developed 63. Launched 97. Troubleshot
  30. Diagnosed 64. Led 98. Uncovered
  31. Directed 65. Maintained 99. Upgraded
  32. Documented 66. Managed 100. Utilized
  33. Doubled 67. Mastered
  34. Educated 68. Mediated

这篇码工求职经验总结就比较靠谱了,非常推荐, 其中关于CS的基础知识一段提到了几个面试中常问的基础问题,今天时间不早了,就挑些软柿子捏捏然后休息吧 ^^.

首先摘录下来这一段:

以前看到有人问说OS/网络层/数据库的东西要不要准备。一般说来问题都取决于简历上的内容,如果简历上没有太多这方面的内容的话,基本上也不怎么会问。不过最基本的概念还是最好能了解,比如 进程和线程的不同,tcp和udp的不同,inner join和outerjoin的不同,等等。这些问题反映了一个人的CS基本功。 比如说简历上要是出现了concurrency的话,那下面这段出自的话里提到的东西应该都要能够了解:

This is just a plug, from me, for you to know about processes, threads and concurrency issues. A lot of interviewers ask about that stuff, and it's pretty fundamental, so you should know it. Know about locks and mutexes and semaphores and monitors and how they work. Know about deadlock and livelock and how to avoid them. Know what resources a processes needs, and a thread needs, and how context switching works, and how it's initiated by the operating system and underlying hardware. Know a little about scheduling. The world is rapidly moving towards multi-core, and you'll be a dinosaur in a real hurry if you don't understand the fundamentals of "modern" (which is to say, "kinda broken") concurrency constructs.

还有就是C++/Java语言的一些基本概念,比如说构造函数、虚函数、接口之类。以及OO 的基本概念。

下面我就总结一下这几个基础问题吧,为了保证充分理解,又能够在面试中说得清楚,中英文的解释都网罗一下。

进程和线程的不同

  • 中文

    进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行. 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。如果有兴趣深入的话,我建议你们看看《现代操作系统》或者《操作系统的设计与实现》。对就个问题说得比较清楚。

  • English

    A process is an executing instance of an application. What does that mean? Well, for example, when you double-click the Microsoft Word icon, you start a process that runs Word. A thread is a path of execution within a process. Also, a process can contain multiple threads. When you start Word, the operating system creates a process and begins executing the primary thread of that process.

Both processes and threads are independent sequences of execution. The typical difference is that threads (of the same process) run in a shared memory space, while processes run in separate memory spaces. Threads are an operating environment feature, rather than a CPU feature(though the CPU typically has operations that make threads efficient). Erlang uses the term "process" because it does not expose a shared-memory multiprogramming model. Calling them "threads" would imply that they have shared memory.

  • Still English

    A process is an executing instance of an application. What does that mean? Well, for example, when you double-click the Microsoft Word icon, you start a process that runs Word. A thread is a path of execution within a process. Also, a process can contain multiple threads. When you start Word, the operating system creates a process and begins executing the primary thread of that process.

It’s important to note that a thread can do anything a process can do. But since a process can consist of multiple threads, a thread could be considered a ‘lightweight’ process. Thus, the essential difference between a thread and a process is the work that each one is used to accomplish. Threads are used for small tasks, whereas processes are used for more ‘heavyweight’ tasks – basically the execution of applications.

Another difference between a thread and a process is that threads within the same process share the same address space, whereas different processes do not. This allows threads to read from and write to the same data structures and variables, and also facilitates communication between threads. Communication between processes – also known as IPC, or inter-process communication – is quite difficult and resource-intensive.

然后还有Multithreading的内容,已经2点了,就先睡觉吧, 刚刚和爸妈视频了一下,希望爸妈健康,快乐。

PS. 今天Amazon today‘s deal,抢了两个 Harmon Kardon CL Precision耳机,才$70每个,看看老婆如果不要的话就卖掉一个 ^^ 下了很大决心准备买三个呢,结果限购一个。算了,人不能太贪心嘛。

@Value,Spring,static-argument

遇到的问题:

    工作中遇到的情况,这次是要在billing-matrix包中的monitor加一个scheduler的feature,这个包也是采用MVC框架,mirror server上跑着这个程序, 访问http://54.203.255.103:8080/monitor/show.do便可检查Production Server的响应速度。而我要做的是统计一下这几项值的大致范围,选择出一个临界点,超过临界点就发邮件通知。原系统中已经有一个scheduler的程序,会周期性的把monitorResult.toString( ) track到log中。而这个monitorResult又含有我需要监测的那些field,所以我要做的事情就比较简单了:

  • 确定各个field的临界值
  • 写好发送emailmethod

@Values annotation 赋值

对于各个参数的赋值按说是没有难度的,但是我这次不想hardcode这些参数,而是用properties文件以及@Values annotation来赋值,这样程序会更加灵活。

关于如何使用@Values以及Spring来把properties中的value注入到Bean中,详见这篇文章

按说跟着步骤来没什么难度,但实际实施起来还是出现了两个问题:

  • 自己不是太清楚classpath到底是指什么,classpathclasspath*有什么区别;
  • @Values总是注入不近来,导致NullPointerException.

关于第一个问题,我引用[这里](http://hi.baidu.com/huahua035/item/ac8a27a994b55bad29ce9d39)的解释:

web.xml中classpath是什么含义 简单理解,classpath就是代表 /WEB-INF /classes/ 这个路径(如果不理解该路径,就把一个web工程发布为war包,然后用winrar查看其包内路径就理解啦)

常用的场景: 在SSH架构中,配置Spring的上下文环境: contextConfigLocation classpath:applicationContext.xml

里面的 classpath:applicationContext.xml
也可以使用 /WEB-INF /classes/ applicationContext.xml 代替

注意: classpath 和 classpath 区别: classpath:只会到你的class路径中查找找文件; classpath:不仅包含class路径,还包括jar文件中(class路径)进行查找

关于第二个问题: 我最初的想法是想把username等field声明为static的,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    @Value("${monitor.email.username:#{null}}")
	static private String username;
	
	@Value("${monitor.email.password:#{null}}")
	static private String password;
	
	@Value("${monitor.email.fromemail:#{null}}")
	static private String fromEmail;
	
	@Value("${monitor.email.toemail.notserious:#{null}}")
	private String toEmailNotSerious;

	@Value("${monitor.email.toemail.serious:#{null}}")
	private String toEmailSerious;

但是事实证明value注入不进来的原因就是static, 发现自己对于static的认识还是不够,下面引用stack overflow上别人的解答

static members belong to the class instead of a specific instance.

It means that only one instance of a static field exists even if you create a million instances of the class or you don't create any. It will be shared by all instances.

Since static methods also do not belong to a specific instance, they can't refer to instance members (how would you know which instance Hello class you want to refer to?). static members can only refer to static members. Instance members can, of course access static members.

Side note: Of course, static members can access instance members through an object reference.

但是没有找到非常适合这个case的解释,我觉得可能Spring在把这个value注入到Bean中时是属于instance范畴的,而不是calss,因为Bean是一个Object,臆测。。总之删掉static就可正常赋值

发送email

我的代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package com.fuhu.osg.billing.matrix.scheduler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.fuhu.osg.billing.matrix.data.json.MonitorObject;
import com.fuhu.osg.billing.matrix.factory.AnalyzeFactory;
import com.fuhu.osg.billing.matrix.util.DataUtil;
import com.fuhu.osg.billing.matrix.util.FileUtil;
import com.fuhu.osg.billing.restclient.MonitorRESTClient;
import com.fuhu.osg.billing.result.MonitorResult;
import com.fuhu.osg.util.Constants;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

@Component
public class MatrixScheduler {

	private static Logger logger = Logger.getLogger(MatrixScheduler.class);

	private static final Map<String, Queue<MonitorResult>> serverMap = new HashMap<String, Queue<MonitorResult>>();

	private static final List<String> serverList = new ArrayList<String>();
	@Autowired
	private MonitorRESTClient client;

	@Value("${monitorEmailUsername}#{null}")
	private String username;

	@Value("${monitorEmailPassword}")
	private String password;

	@Value("${monitorFromEmail}")
	private String fromEmail;

	@Value("${monitorToEmailNotSerious}")
	private String toEmailNotSerious;

	@Value("${monitorToEmailSerious}")
	private String toEmailSerious;

	boolean serious;

	@Scheduled(cron = "${monitor.scheduler}")
	public void monitorActivated() {
		MonitorResult result = client.monitorStatus();

		Queue<MonitorResult> queue = null;
		if (serverMap.get(result.getServerId()) == null) {
			queue = new ArrayBlockingQueue<MonitorResult>(48);
			serverMap.put(result.getServerId(), queue);
			serverList.add(result.getServerId());
		} else {
			queue = serverMap.get(result.getServerId());
		}

		if (queue.size() == 48) {
			queue.poll();
		}
		if (result.getStatus().equals(Constants.SUCCESS)) {
			queue.add(result);
		} else {
			queue.add(new MonitorResult());
		}
		logger.trace(result.toString());
		// for data analysis
		if (result.getTotalRTT() != 0.0) {
			System.out.println("Result is --> " + result.toString());
		}
		StringBuilder sBuilder = new StringBuilder();
		if (result.getCoppaRTT() > 500) {
			// send email
			String content = "CoppaRTT is above 500";
			serious = false;

			sendEmail(content, username, password, fromEmail, toEmailNotSerious, toEmailSerious);
		}

	}

	public static Queue<MonitorResult> getDataQueue(String serverId) {
		return serverMap.get(serverId);
	}

	public static List<String> getServerList() {
		return serverList;
	}

//	inner class uses username & password, so use final parameter.
	public void sendEmail(String content, final String username, final String password, String fromEmail, String toEmailNotSerious , String toEmailSerious) {
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com");
		props.put("mail.smtp.socketFactory.port", "465");
		props.put("mail.smtp.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory");
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.port", "465");

		Session session = Session.getDefaultInstance(props,
				new javax.mail.Authenticator() {
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication(username, password);
					}
				});

		try {

			Message message = new MimeMessage(session);
			message.setFrom(new InternetAddress(fromEmail));
			if (serious) {
				message.setRecipients(Message.RecipientType.TO,
						InternetAddress.parse(toEmailSerious));
			} else {
				message.setRecipients(Message.RecipientType.TO,
						InternetAddress.parse(toEmailNotSerious));
			}
			message.setSubject("Server Monitor Warning");
			message.setText("Attention, server in danger " + content);
			Transport.send(message);
		} catch (MessagingException e) {
			throw new RuntimeException(e);
		}
	}

}

这里sendEmail()有一点tricky的地方,就是用了final variable, final String username & final String password, 这是因为sendEmail()method中的inner class使用了这两个argument. 原因:

There are two main reasons you might want to mark an argument final. First, if you're planning on using the argument in an anonymous inner class, then you must mark it final so that it can be referenced in that class. This is actually a pretty common use case for marking arguments final.

The other common reason to mark arguments final is to prevent yourself from accidentally overwriting them. If you really don't want to change the arguments, then perhaps you should mark them final so that if you actually do, you'll get the error at compile-time rather than finding out at runtime that your code has a bug.

详见stack overflow的解释。

Markdown首行缩进:

&ensp;&ensp;&ensp;&ensp;这是段落1 &emsp;&emsp;&emsp;&emsp;这是段落2 &nbsp;&nbsp;&nbsp;&nbsp;这是段落3 无段落

效果如下:

    这是段落1     这是段落2     这是段落3 无段落

终于搞定博客了

Hello World...

搞定博客!OH Yeah!

前前后后搞了好几天,终于算是告一段落了,从最开始的Jekylloctopress,最后到Hexo,看了很多教程,期间学习了gitMarkdown,总是有收获的嘛!

从最终结果来看,主要参考下面几篇文章就可以搭建出来自己的Hexo Blog

还有一些有待完善的地方,比如一些可以留言或者订阅的plugin啊,另外还有一个小tip,就是md文件标记多个tag的时候使用YAML格式:

tags: 换行-123 换行-456