Python的学习笔记--函数式编程

函数式编程 主要思想是把运算过程尽量写成一系列嵌套的函数调用,不严谨的说:可以把函数的引用传递给变量。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> abs(-10)
10
>>> f=abs
>>> f(-10)
10
```
`f`就引用了abs函数的地址。

1. 可以把函数当成参数传递给另一个函数:

```python
def add(x,y,f):
return f(x)+f(y)
print(add(-1,2,abs))
  1. 函数也可以当成返回值:

    1
    2
    3
    def getMethod():
    return abs
    print(getMethod()(-1))

    打印结果是:1

  2. python也支持lambda表达式

    1
    2
    f=lambda x:x+x
    print(f(10))

    打印结果是:10

  3. 可以固定一个函数的默认值,返回一个新函数

    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
         import functools
    def add(x="2"):
    print(x)
    add()
    add1=functools.partial(add, x="5")
    add1()
    ```
    打印结果:`2 5`

    我们使用`functools.partial`方法把`add`的默认值修改成一个新的函数`add1`


    #### 常用的几个函数

    - map和reduce使用

    `map`函数的格式可以大致的表示为:`map(func,[])`,其功能就是把数组的每一个元素代入到`func`函数中,具体的实现功能如下:

    `list(map(abs,[-1,3,4,-6]))`,打印结果是:[1,3,4,5]

    我们可以根据其定义编写对应的功能:

    ```python
    def map1(func,arr):
    l=[]
    for x in arr:
    yield func(x)

    print(map1(abs,[1,-3,-4,6]))
    ```

    `reduce`是一个累计的函数,把上次计算的结果,当成下次运行的一个参数:`s1=f(x,y);s2=f(s1,z);`

    ``` python
    def add(x,y):
    return x+y
    print(reduce(add,[1,-3,-4,6]))
    ```
    计算结果:`1-3-4+6=0`

    用python代码来表示`reduce`

    ``` python
    def reduce1(func,arr):
    s=0
    for x in arr:
    s=func(s,x)
    return s;

Python的学习笔记--高级特性

数组的切片

定义一个数组

1
arr=list(range(100))
  1. 数组取前3个元素 arr[0:3],0可以省略,arr[:3],打印结果:[0,1,2]

  2. 数组取后面三个元素: arr[-3:0],也可写为:arr[-3:],打印结果:[97,98,99]

  3. 数组取后面三个元素: arr[97:],是跳过前97个数字,打印结果:[97,98,99]

  4. 可以指定取值的间隔 arr[:10:2],打印结果:[0, 2, 4, 6, 8]
    如果在全部范围内查询,可以省略查询的个数,arr[::2]这样打印出来所有的偶数。

  5. 切片的方法同样适用于tuple

  6. 字符串可以看成是字符的数组,可以使用,"ABCDEFG"[:3] 输出结果ABC

迭代循环

  1. list的循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
         arr=list(range(10))
    for a in arr:
    print(a)
    ```

    2. `dict`循环

    ```python
    dict={"a":1,"b":2,"c":3}
    for a in dict:
    print(a)
    ```

    ```python
    dict={"a":1,"b":2,"c":3}
    for x,y in dict.items():
    print(x,y)
    ```

    ``` cte
    a 1
    b 2
    c 3

  2. 字符串循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
         for a in "ABCD": 
    print(a)

    ```
    4. 多个变量
    ```python
    for x, y in [(1, 1), (2, 4), (3, 9)]:
    print(x, y)

    ```
    打印结果:
    ``` cte
    1 1
    2 4
    3 9
  3. 带索引的循环写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for i, value in enumerate(['A', 'B', 'C']):
    print(i, value)

    ```
    打印结果:

    ```cte
    0 A
    1 B
    2 C
  4. 判断能否被迭代

    1
    2
    3
    from collections import Iterable
    isinstance('abc', Iterable)

列表生成式

列表生成式可以更简单的把生成一个list或者tuple.

定义一个100的数组,arr=list(range(100))

  1. 定义一个100偶数的数组

    1
    2
    3
    4
    arr=[2 * x for x in list(range(100))]

    或者arr=[x for x in list(range(200)) if x%2==0]

    打印结果:[0,2,4...198]

  2. 定义两个循环生成一个组合

    1
    str=[a+b for a in "ABC"  for b in "XYZ"]  

    打印结果:['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

  3. 使用多个变量

    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
         dict = {'a': 'A', 'b': 'B', 'c': 'C' }
    dic=[k + '=' + v for k, v in dict.items()]
    print(dic)
    ```

    打印结果:`['a=A', 'b=B', 'c=C']`

    4. 使用函数

    ``` python
    arr=[x.upper() for x in "abc"]
    print(arr)

    ```

    打印结果:`['A', 'B', 'C']`

    获得当前路径,可以用一句代码
    ```python
    import os
    fs=[d for d in os.listdir('.')]
    print(fs)
    ```


    5. 表达式可以赋值给一个变量,实现延迟加载

    ``` python
    g = (2 * x for x in range(10))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))

    打印结果:0,2,4,6,8

    也可以使用循环打印:

    1
    2
    3
    g = (2 * x for x in range(10))
    for x in g:
    print(x)

Python的学习笔记--函数

函数的定义


python使用def来定义

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
def print_str(x):
print (x)
```
调用`print_str("12")` 打印`12`


#### 默认参数
----------------------------

`python`支持默认参数。

```python
def print_str(x,y="end"):
print (x,y)
```

调用`print_str("12")`,不传递y参数 打印`12 end`
调用`print_str("12","continue")` 打印`12 continue`

如果是多个默认参数,可以根据参数的名称来指定参数。

``` python
def print_str(x,y="y",z="z"):
print ("x:",x)
print ("y:",y)
print ("z:",z)

当调用print_str(1,2),打印结果:

1
2
3
4
5
6
7
8
9
10
x: 1
y: 2
z: z
```

当调用`print_str(1,z=2)`,打印结果:
``` cte
x: 1
y: y
z: 2

使用默认参数需要注意一个问题:默认定义的时候,默认参数值已近计算出来,如果是一个默认参数是一个引用,则会发生改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def add_dict(arr=[]):
arr.append("end")
print (arr)
add_dict()
add_dict()
add_dict()
```

打印结果如下:

```cte
['none']
['none', 'none']
['none', 'none', 'none']

所以,如果使用可变的引用变量,则注意这种形式。可以使用None来代替:

1
2
3
4
5
6
def add_dict(arr=None):
if arr is None:
arr=[]

arr.append("end")
print (arr)

可变参数


python支持可变的个数的参数,在原来的参数上面增加一个*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def print_str(*x):
print (x)
print_str(1,2,3,4)
```
打印结果如下:`(1, 2, 3, 4)`

> 可变参数在函数调用时自动组装为一个tuple

如果想把一个数组的元素当成默认参数传到方法里面,该如何操作?

``` python
def print_str(*x):
print (x)

arr=[1,2,3,4]
print_str(arr)

打印结果:([1, 2, 3, 4],),这个是把arr当成一个list类型的参数传入到方法中,打印出来是一个tuple([],)类型。

所以在python允许list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def print_str(*x):
print (x)

arr=[1,2,3,4]
print_str(*arr)
```
打印结果:`(1, 2, 3, 4)`

#### 关键字参数
-----------------------------

关键字参数是把默认参数当成一个`dict`的类型,使用方法是`**`,我们定义一个关键字参数:

``` python
def print_str(x,**arg):
print (x,arg)
print_str(1)

打印结果是:1 {}

调用print_str(1,a=1,b=2,c=3),打印结果:1 {'a': 1, 'b': 2, 'c': 3}

同样如果想把一个dict类型的参数传递进来,也需要使用**

1
2
3
4
def print_str(x,**arg):
print (x,arg)
dic={'a': 1, 'b': 2, 'c': 3}
print_str(1,**dic)

打印结果:1 {'a': 1, 'b': 2, 'c': 3}

注意: dic这个中参数传递是一种拷贝,在函数内部修改不会影响原来的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
def print_str(x,**arg):
arg["a"]=10
print (x,arg)
dic={'a': 1, 'b': 2, 'c': 3}
print_str(1,**dic)
print(dic)
```

打印结果:

``` cte
1 {'a': 10, 'b': 2, 'c': 3}
{'a': 1, 'b': 2, 'c': 3}

MarkDown插入数学公式

最近想学下数学方面的东西,但发现公式的插入是比较头疼的事情。在Markdown的环境下,有一个latex数学公式官网的写法,用起来很是强大,只要引入下面的js就可以。

1
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>

$$...$$包括,行内公式用$...$包括
比如想写一个 $$x_{11}$$ ,具体的写法如下:

1
$$x_{11}$$

常用的希腊字母写法

|字母|公式||字母|公式|
|$$\alpha$$|$$\alpha$$||$$\pi$$|$$\pi$$|
|$$\beta$$|$$\beta$$||$$\Sigma$$|$$\Sigma$$|
|$$\gamma$$|$$\gamma$$||$$\Gamma$$|$$\Gamma$$|
|$$\delta$$|$$\delta$$||$$\Delta$$|$$\Delta$$|
|$$\epsilon$$|$$\epsilon$$||$$\varphi$$|$$\varphi$$|
|$$\eta$$|$$\eta$$||$$\upsilon$$|$$\upsilon$$|
|$$\phi$$|$$\phi$$||$$\Phi$$|$$\Phi$$|
|$$\omega$$|$$\omega$$||$$\Omega$$|$$\Omega$$|
|$$\theta$$|$$\theta$$||$$\Theta$$|$$\Theta$$|
|$$\lambda$$|$$\lambda$$||$$\Lambda$$|$$\ambda$$|
|$$\mu$$|$$\mu$$||$$\nu$$|$$\nu$$|
|$$\xi$$|$$\xi$$||$$\partial$$|$$\partial$$|

常用的上下标

|字母|公式||字母|公式|
|$$x^2$$|$$x^2$$||$$\sqrt[x]y$$|$$\sqrt[x]y$$|
|$$x_i$$|$$x_i$$||$$x_{ij}$$|$$x_{ij}$$|
|$$\dots$$|$$\dots$$||$$\cdots$$|$$\cdots$$|

运算符

四则运算符(operator) 例如 + - * /等可以直接输入

|字母|公式||字母|公式|
|$$\pm$$|$$\pm$$||$$\times$$|$$\\times$$|
|$$\cap$$|$$\cap$$||$$\cup$$|$$\cup$$|
|$$\geq$$|$$\geq$$||$$\leq$$|$$\leq$$|
|$$\neq$$|$$\neq$$||$$\approx$$|$$\approx$$|
|$$\sum_{i=0}^nx_iy_i$$|$$\sum_{i=0}^nx_iy_i$$||$$\sum_1^n$$|$$\sum_1^n$$|
|$$\int_1^n$$|$$\int_1^n$$||$$\lim_{x \to \infty}$$|$$\lim_{x \to \infty}$$|
|$$\frac{y}{x}$$|$$\frac{y}{x}$$||$$\equiv$$|$$\equiv$$|

矩阵和行列式

$$\begin{matrix}…\end{matrix}$$,中间使用&分开

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
$$
\begin{matrix}
a_{11} & x & x^2 \\
a_{21} & y & y^2 \\
a_{31} & z & z^2 \\
\end{matrix}
$$

````
对应的结果如下:
$$
\begin{matrix}
a_{11} & x & x^2 \\
a_{21} & y & y^2 \\
a_{31} & z & z^2 \\
\end{matrix}
$$

行列式是在矩阵的前面和末尾加个`|`,写法如下:

```cte
$$
X=\left|
\begin{matrix}
x_{11} & x_{12} & \cdots & x_{1d}\\
x_{21} & x_{22} & \cdots & x_{2d}\\
\vdots & \vdots & \ddots & \vdots\\
x_{m1} & x_{m2} & \cdots & x_{md}\\
\end{matrix}
\right|
$$

$$
X=\left|
\begin{matrix}
x_{11} & x_{12} & \cdots & x_{1d}\
x_{21} & x_{22} & \cdots & x_{2d}\
\vdots & \vdots & \ddots & \vdots\
x_{m1} & x_{m2} & \cdots & x_{md}\
\end{matrix}
\right|
$$

常用箭头

|字母|公式||字母|公式|
|$$\leftarrow$$|$$\leftarrow$$||$$\rightarrow$$|$$\rightarrow$$|
|$$\longleftarrow$$|$$\longleftarrow$$||$$\longrightarrow$$|$$\longrightarrow$$|
|$$\leftrightarrow$$|$$\leftrightarrow$$||$$\longleftrightarrow$$|$$\longleftrightarrow$$|
|$$\Leftarrow$$|$$\Leftarrow$$||$$\Rightarrow$$|$$\Rightarrow$$|
|$$\Longleftarrow$$|$$\Longleftarrow$$||$$\Longrightarrow$$|$$\Longrightarrow$$|
|$$\Leftrightarrow$$|$$\Leftrightarrow$$||$$\Longleftrightarrow$$|$$\Longleftrightarrow$$|

各种括号用 () [] { } \langle\rangle 等命令表示,注意花括号通常用来输入命令和环境的参数,所以在数学公式中它们前面要加 \。可以在上述分隔符前面加 \big \Big \bigg \Bigg 等命令来调整大小。

方程式和方程组

  • 方程公式

    1
    2
    3
    \begin{equation}
    E=mc^2
    \end{equation}

    \begin{equation}
    E=mc^2
    \end{equation}

  • 分段函数

    1
    2
    3
    4
    5
    6
    7
    8
    $$
    f(n) =
    \begin{cases}
    n/2, & \text{if $n$ is even} \\
    3n+1, & \text{if $n$ is odd}
    \end{cases}
    $$

$$
f(n) =
\begin{cases}
n/2, & \text{if $n$ is even} \
3n+1, & \text{if $n$ is odd}
\end{cases}
$$

  • 方程组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $$
    \left\{
    \begin{array}
    a_1x+b_1y+c_1z=d_1 \\
    a_2x+b_2y+c_2z=d_2 \\
    a_3x+b_3y+c_3z=d_3
    \end{array}
    \right.
    $$

$$
\left{
\begin{array}
a_1x+b_1y+c_1z=d_1 \
a_2x+b_2y+c_2z=d_2 \
a_3x+b_3y+c_3z=d_3
\end{array}
\right.
$$

常用的公式

  • 线性模型

    1
    $$h(\theta)=\sum_{j=0}^n\theta_ix_j$$

$$h(\theta)=\sum_{j=0}^n\theta_ix_j$$

  • 均方误差

    1
    $$J(\theta)=\frac{1}{2m}\sum_{i=0}^m(y^i-h_{\theta}(x^i))^2$$

    $$J(\theta)=\frac{1}{2m}\sum_{i=0}^m(y^i-h_{\theta}(x^i))^2$$

  • 批量梯度都下降

    1
    $$\frac{\partial J(\theta)}{\partial\theta_j}=-\frac{1}{m}\sum_{i=0}^m(y^i-h_{\theta}(x^i))x_j^i$$   

$$\frac{\partial J(\theta)}{\partial\theta_j}=-\frac{1}{m}\sum_{i=0}^m(y^i-h_{\theta}(x^i))x_j^i$$

  • 微积分公式

    1
    $$S=\int_a^bf(x)dx$$

$$S=\int_a^bf(x)dx$$

  • 矩阵变换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $$X=\left(
    \begin{matrix}
    x_{11} & x_{12} & \cdots & x_{1d}\\
    x_{21} & x_{22} & \cdots & x_{2d}\\
    \vdots & \vdots & \ddots & \vdots\\
    x_{m1} & x_{m2} & \cdots & x_{md}\\
    \end{matrix}
    \right)
    =\left(
    \begin{matrix}
    x_1^T \\
    x_2^T \\
    \vdots\\
    x_m^T \\
    \end{matrix}
    \right)
    $$

$$X=\left(
\begin{matrix}
x_{11} & x_{12} & \cdots & x_{1d}\
x_{21} & x_{22} & \cdots & x_{2d}\
\vdots & \vdots & \ddots & \vdots\
x_{m1} & x_{m2} & \cdots & x_{md}\
\end{matrix}
\right)
=\left(
\begin{matrix}
x_1^T \
x_2^T \
\vdots\
x_m^T \
\end{matrix}
\right)
$$

Java特殊字符串分隔

首先看一段代码:

1
2
3
4
String[] splitArr = "1|23242|3|4".split("|");
for (String s : splitArr) {
System.out.println(s);
}

输出结果是:

1
2
3
4
5
6
7
8
9
10
11
1
|
2
3
2
4
2
|
3
|
4

在Java中有三个特殊字符:.,\,|,这几个字符分割的时候,需要用\\进行转义.

正确的代码如下:

1
2
3
4
String[] splitArr = "1|23242|3|4".split("\\|");
for (String s : splitArr) {
System.out.println(s);
}

Python的学习笔记---dict和set

dict类型的使用

python有一个dict类型,存储格式是key:value的形式,在其他语言有的成为mapDictionary.

1
2
3
>>> dict={"a":1,"b":3}
>>> dict["a"]
1

由于dict是根据key查询数据,所以查询的效率比list要高出不少。

取值的时候,key如果不存在则会报异常。所以为了更安全的使用dict可以使用前判断下:

1
2
>>> "a" in dict
True

或者可以使用get函数,如果不存在,则返回None数据,也可以指定默认值:

1
2
3
4
>>> dict.get("c")
>>> dict.get("c",1)
1
>>>
  1. dict的key必须是不可变对象
  2. dict的内部顺序和存储的先后顺序没有关系
  3. 查找和插入的速度极快,不会随着key的增加而变慢
  4. 需要占用大量的内存,内存浪费多。

dict可以使用pop方法对数据进行删除:

1
2
3
4
>>> dict.pop("b")
3
>>> dict
{'a': 1}

set类型

set类型与list相似,是一种不会有重复数据的数组:

1
2
3
4
5
6
>>> list=[1,2,1,2,3,3,4,5,1,1,1,1,5,6]
>>> list
[1, 2, 1, 2, 3, 3, 4, 5, 1, 1, 1, 1, 5, 6]
>>> set(list)
{1, 2, 3, 4, 5, 6}
>>>

set可以使用add()方法增加数据,如果增加重复数据,但不会有效果。

1
2
3
4
5
6
7
8
9
10
>>> list=[1,2,1,2,3,3,4,5,1,1,1,1,5,6]
>>> aset=set(list)
>>> aset
{1, 2, 3, 4, 5, 6}
>>> aset.add(7)
>>> aset
{1, 2, 3, 4, 5, 6, 7}
>>> aset.add(7)
>>> aset
{1, 2, 3, 4, 5, 6, 7}

使用remove移除数据:

1
2
3
>>> aset.remove(1)
>>> aset
{2, 3, 4, 5, 6, 7}

set可以看成数学中的集合,可以进行交集并集的计算:

1
2
3
4
5
6
7
>>> a=set([1,2,3,4,5])
>>> b=set([4,5,6,7,8])
>>> a&b
{4, 5}
>>> a|b
{1, 2, 3, 4, 5, 6, 7, 8}
>>>

Python的学习笔记---list和tuple

今天学习了python的list和tuple的使用,python中的数组类型的结构比其他语言更为灵活,下面我们说说他们的用法:

list使用

  1. 定义一个list

    1
    2
    3
    >>> arr=[1,2,3,4,5,6]
    >>> arr
    [1, 2, 3, 4, 5, 6]

    arr就是定义的数组,使用索引来获得数组里面的数据如:arr[0],arr[1]等等,在python数组有一个特殊的用法,使用-1,-2可以取倒数第一或第二的值。

    1
    2
    3
    4
    >>> arr[0]
    1
    >>> arr[-1]
    6

    如果超出界限,会抛出异常:

    1
    2
    3
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    IndexError: list index out of range

    由于python是弱类型的语言,所以数组里面可以存储不同类型的数据:

    1
    2
    3
    >>> arr=[1,2,"hello",[1,2,34]]
    >>> arr
    [1, 2, 'hello', [1, 2, 34]]

    如果想拿到34这个值,可以类似二维数组那样arr[3][2]

    可以使用range函数快速定义个有序的数组:

    1
    2
    3
    >>> list(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>>

    range的具体的使用方法range(start, stop[, step])
    range(1,10,2)代表的从1-10每次长度的2

  2. 数组的相关的函数

    • len 获得数组的长度

      1
      2
      >>> len(arr)
      4
    • append 增加一个元素

      1
      2
      3
      4
      >>> arr.append("1111")
      >>> arr
      [1, 2, 'hello', [1, 2, 34], '1111']
      >>>
    • insert插入数据

      1
      2
      3
      >>> arr.insert(1,213)
      >>> arr
      [1, 213, 2, 'hello', [1, 2, 34], '1111']

      insert(1,213)代表在1位置,插入一个213的数字

    • pop删除元素

      poppython中删除元素的方法,arr.pop()默认删除最后一个元素,arr.pop(i)代表可以删除指定位置的元素:

      1
      2
      3
      4
      5
      >>> arr.pop()
      '1111'
      >>> arr
      [1, 213, 2, 'hello', [1, 2, 34]]
      >>>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
                >>> arr.pop(1)
      213
      >>> arr
      [1, 2, 'hello', [1, 2, 34]]
      ```

      #### tuple的使用

      `tuple`是一个有序的数组,和`list`类似,`tuple`的特点是定义后不能在被修改,这样可以让代码中的数据更加安全。

      定义`tuple`使用`()`,例如定义一个`tuple`如下:

      ```python
      >>> tup=(1,2,3)
      >>> tup
      (1, 2, 3)

由于tuple不可修改,所以不能使用append,insert等修改元祖的方法。

如果定义一个只有一个元素的tuple:

1
2
3
>>> tup=(1)
>>> tup
1

这样我们发现,tup不是一个元祖,而是一个数字。原来是只用一个元素的时候,tuple中的()与数学运算中的括号冲突了,所以当定义只有一个元素的tuple的时候,需要在最后加一个,,方法如下:

1
2
3
>>> tup=(1,)
>>> tup
(1,)

如果在tuple中定义一个数组,如果改变数组的值,tuple中的值也会发生改变:

1
2
3
4
5
>>> tup=(1,[1,2])
>>> tup[1][0]="a"
>>> tup[1][1]="b"
>>> tup
(1, ['a', 'b'])

jstack发现多线程死锁

在多线程的使用中,有时会碰到死锁,死锁会造成应用程序阻塞,浪费系统资源。下面探讨如何发现和解决死锁:

产生死锁

首先先写一段能够产生死锁的代码:

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
private static Object lock1=new Object();
private static Object lock2=new Object();
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
synchronized (lock1){
System.out.println("线程1获得 lock1");
SleepUtils.Sleep(1);
synchronized (lock2){
System.out.println("线程1获得 lock2");
}
}
System.out.println("线程1结束 ");
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (lock2){
System.out.println("线程2获得 lock2");
SleepUtils.Sleep(1);
synchronized (lock1){
System.out.println("线程2获得 lock1");
}
}
System.out.println("线程2结束 ");
}
}.start();
}

运行上面的结果,线程会各自阻塞在同步锁的那个地方,产生了死锁,运行结果如下:

1
2
线程1获得 lock1
线程2获得 lock2

我们使用jps命令, 查询Java的线程,如下:

jps

使用jstack 16071命令查看堆栈信息

jps

从上面可以看出来,两个线程都在等待一个内存地址,这个就是我们的死锁

deepin系统中idea乱码

deepin中idea乱码

在deepin中使用idea中文乱码,是缺少字体的原因,所以需要安装字体:

1
aptitude search uming 

如果正确安装会显示如下信息:

deepin

如果没有正确安装,使用下面命令安装:

1
aptitude install fonts-arphic-uming

安装完成后重启下idea就可以了。

写了一个无聊的小游戏--无聊碰碰球

实现功能点

  1. 小球出生有一个等级和收入
  2. 小球每次随机获得一个目标点,在一定的时间范围内,然后移动到目标点,超时和到达则重新获取目标点。
  3. 小球在移动的过程中,碰到相同的size的球,会自动融合,成为一个新的球,size和gain是原来的两倍。
  4. 利用本地的存储对数据进行存储和恢复,利用平均收益和离线时间,计算离线收益。
  5. 增加出生速度,运动速度的属性的时候都需要对应的收益,玩家控制好金钱分配,把收益最大化。