Java 到底是值传递还是引用传递?

值传递概念:

值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递:

所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

阅读更多

ServerSocket 和 Socket 通信实例

Socket

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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1",8888);

//构建IO
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//向服务器端发送一条消息
bw.write("测试客户端和服务器通信,服务器接收到消息返回到客户端\n");
bw.flush();

//读取服务器返回的消息
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String mess = br.readLine();
System.out.println("服务器:"+mess);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

ServerSocket

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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(8888);
System.out.println("启动服务器....");
Socket s = ss.accept();
System.out.println("客户端:"+s.getInetAddress().getLocalHost()+"已连接到服务器");

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//读取客户端发送来的消息
String mess = br.readLine();
System.out.println("客户端:"+mess);

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write(mess+"\n");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

参考文章

-

线程 方法

method 什么类的方法 描述
wait() notify() notifyAll() Object的本地final方法,无法被重写 实现线程间的通信
在线程中调用 wait() 方法,将阻塞当前线程,直至等到其他线程调用了调用 notify() 方法或 notifyAll() 方法进行通知之后,当前线程才能从 wait() 方法出返回,继续执行下面的操作。
park() unpark() 工具类LockSupport 1.park和unpark是以线程为单位精确阻塞和唤醒线程的;
2.阻塞和唤醒的先后执行顺序可以不一样;
await和signal Condition Object的wait和notify/notify是与对象监视器配合完成线程间的等待/通知机制,而Condition与Lock配合完成等待通知机制,前者是java底层级别的,后者是语言级别的,具备更高的可控制性和扩展性
join() thread 控制线程执行顺序
阅读更多

volatile

定义

volatile变量规则:对volatile变量的写入操作必须在对该变量的读操作之前执行

volatile变量规则只是一种标准,要求JVM实现保证volatile变量的偏序语义。结合程序顺序规则、传递性,该偏序语义通常表现为两个作用:

  • 保持可见性
  • 禁用重排序(读操作禁止重排序之后的操作,写操作禁止重排序之前的操作)
阅读更多

常见内存溢出错误

Exception in thread “main”: java.lang.OutOfMemoryError: Java heap space

原因:对象不能被分配到堆内存中。

Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space

原因:类或者方法不能被加载到老年代。它可能出现在一个程序加载很多类的时候,比如引用了很多第三方的库。

阅读更多

JVM内存结构

概述

img_8.png

JVM内存结构主要有三大块:·堆内存、方法区和栈·。
堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden空间、From Survivor空间、To Survivor空间,
默认情况下年轻代按照8:1:1的比例来分配;

方法区存储类信息、常量、静态变量等数据,是线程共享的区域,为与Java堆区分,方法区还有一个别名Non-Heap(非堆);
栈又分为java虚拟机栈和本地方法栈主要用于方法的执行。

xx xxxxxxxx desc
堆(Heap) 线程共享 所有的对象实例以及数组都要在堆上分配。
回收器主要管理的对象。
方法区(Method Area) 线程共享 Non-Heap(非堆)
存储类信息、常量、静态变量、即时编译器编译后的代码。
方法栈(JVM Stack) 线程私有 存储局部变量表、操作栈、动态链接、方法出口,对象指针。
本地方法栈(Native Method Stack) 线程私有 为虚拟机使用到的Native 方法服务。如Java使用c或者c++编写的接口服务时,代码在此区运行。
程序计数器(Program Counter Register) 线程私有 PC寄存器(PC Register)
当前线程所执行的字节码的行号指示器。指向下一条要执行的指令。

在通过一张图来了解如何通过参数来控制各区域的内存大小
img_7.png

1
2
3
4
5
6
7
-Xms设置堆的最小空间大小
-Xmx设置堆的最大空间大小
-XX:NewSize设置新生代最小空间大小
-XX:MaxNewSize设置新生代最大空间大小
-XX:PermSize设置永久代最小空间大小
-XX:MaxPermSize设置永久代最大空间大小
-Xss设置每个线程的堆栈大小
阅读更多

centos install nginx

prepare

1
sudo yum install -y gcc gcc-c++ 
1
sudo yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel

root 安装PCRE库

1
2
3
4
5
6
cd /usr/local/
wget http://jaist.dl.sourceforge.net/project/pcre/pcre/8.33/pcre-8.33.tar.gz
tar -zxvf pcre-8.33.tar.gz
cd pcre-8.33
./configure
make && make install
阅读更多