
几乎所有的操作系统都支持进程的概念,所有运行中的任务通常对应一个进程(Process)。
进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。
独立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源,每一个进程都拥有自己私有的地址空间。在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间。动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。在进程中加入了时间的概念。进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的。并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响。大部分操作系统都支持多进程并发运行,现代的操作系统几乎都支持同时运行多个任务。 多线程则扩展了多进程的概念,使得同一个进程可以同时并发处理多个任务。
线程(Thread)也被称作轻量级进程(Lightweight Process),线程是进程的执行单元。
对于绝大多数的应用程序来说,通常仅要求有一个主线程,但也可以在该进程内创建多条顺序执行流,这些顺序执行流就是线程,每个线程也是互相独立的。
线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程。
线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不拥有系统资源,它与父进程的其他线程共享该进程所拥有的全部资源。
因为多个线程共享父进程里的全部资源,因此编程更加方便;但必须更加小心,因为需要确保线程不会妨碍同一进程里的其他线程线程可以完成一定的任务,可以与其他线程共享父进程中的共享变量及部分环境,相互之间协同来完成进程所要完成的任务。
简单来说:
Java语言提主要供了两种实现线程的方式:
实现步骤:
实现步骤:
start()方法来启动该线程。线程的五种状态:
新建状态(New):线程对象实例化后就进入了新建状态。就绪状态(Runnable):线程对象实例化后,其他线程调用了该对象的start()方法,虚拟机便会启动该线程,处于就绪状态的线程随时可能被调度执行。运行状态(Running):线程获得了时间片,开始执行。只能从就绪状态进入运行状态。阻塞状态(Blocked):线程因为某个原因暂停执行,并让出CPU的使用权后便进入了阻塞状态。 结束状态(Dead):线程正常执行完或异常退出时,进入了结束状态。返类型 | 构造器/方法 | 说明 |
|---|---|---|
| Thread() | 分配新的 Thread 对象。 |
| Thread(Runnable target) | 分配新的 Thread 对象。 |
| Thread(Runnable target, String name) | 分配新的 Thread 对象。 |
static Thread | currentThread() | 返回对当前正在执行的线程对象的引用。 |
static void | sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。 |
static void | sleep(long millis, int nanos) | 在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)。 |
static void | yield() | 暂停当前正在执行的线程对象,并执行其他线程。 |
void | start() | 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 |
long | getId() | 返回该线程的标识符。 |
String | getName() | 返回该线程的名称。 |
int | getPriority() | 返回线程的优先级。 |
boolean | isAlive() | 测试线程是否处于活动状态。 |
void | join() | 等待该线程终止。 |
void | join(long millis) | 等待该线程终止的时间最长为 millis 毫秒。 |
void | join(long millis, int nanos) | 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒 |
void | setName(String name) | 改变线程名称,使之与参数 name 相同。 |
void | setPriority(int newPriority) | 更改线程的优先级。参数范围1,10 |
许多在单线程情况下的代码放到多线程环境下容易出现线程安全问题。
为了解决线程安全问题,Java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块。
同步代码块的语法格式如下:
synchronized (obj) {
//同步代码块
}obj叫做同步监视器(锁对象),任何线程进入下面同步代码块之前必须先获得对obj的锁;其他线程无法获得锁,也就执行同步代码块。
任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后该线程会释放对该同步监视器的锁定。
除了同步代码块,Java的多线程安全支持还提供了同步方法
对于synchronized修饰的实例方法(非static方法),无须显式指定同步监视器,同步方法的同步监视器就是this,也就是调用该方法的对象。
从Java5开始,Java提供了一种功能更强大的线程同步机制——通过显式定义同步锁对象来实现同步,在这种机制下,同步锁由Lock对象充当。
Lock提供了比synchronized方法和synchronized代码块更广泛的锁定操作,Lock允许实现更灵活的结构,可以具有差别很大的属性。
Lock是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
在实现线程安全的控制中,比较常用的是 ReentrantLock(可重入锁)。使用该Lock对象可以显式地加锁、释放锁。
当两个线程相互等待对方释放同步监视器时就会发生死锁,Java虚拟机没有监测,也没有采取措施来处理死锁情况,所以多线程编程时应该采取措施避免死锁出现。
一旦出现死锁,整个程序既不会发生任何异常,也不会给出任何提示,只是所有线程处于阻塞状态,无法继续。
在系统中出现多个同步监视器的情况下很容易发生死锁。
才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized代码块的代码或是中途遇到wait(),再次释放锁。也就是说,notify/notifyAll()的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况。所以在编程中,尽量在使用了notify/notifyAll()后立即退出临界区,以唤醒其他线程。计算机网络是指两台或更多的计算机组成的网络,在同一个网络中,任意两台计算机都可以直接通信,因为所有计算机都需要遵循同一种网络协议。
TCP/IP协议泛指互联网协议,其中最重要的两个协议是TCP协议和IP协议。
只有使用TCP/IP协议的计算机才能够联入互联网,使用其他网络协议(例如NetBIOS、AppleTalk协议等)是无法联入互联网的。
MAC地址(物理地址),用于表示网卡的唯一编号。
一般是在网卡出厂时由厂家写入硬件的唯一地址。
在网络中,一个IP地址用于唯一标识一个网络接口(Network Interface)。
一台联入互联网的计算机肯定有一个IP地址,但也可能有多个IP地址。
IP地址分为IPv4和IPv6两种。
IPv4采用32位地址,类似192.168.1.11。
IPv6采用128位地址,类似2001:0DA8:100A:0000:0000:1020:F2F3:1428。
特殊IP地址:127.0.0.1 本机地址
如果一台计算机只有一个网卡,并且接入了网络,那么,它有一个本机地址127.0.0.1,还有一个IP地址,例如192.168.1.11,可以通过这个IP地址接入局域网络。
如果一台计算机有两块网卡,那么除了本机地址,它可以有两个IP地址,可以分别接入两个网络。比如服务器
return Json() --> json字符串--> ajax把Json字串串转为Json对象
请求 ajax发送Json对象 -->json字符串–> Controller.action(类 实例)进行了反序列化
对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,通过网络将这种二进制流传输到另一个网络节点。
序列化机制允许将实现序列化的Java对象转换成字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以备以后重新恢复成原来的对象。
序列化机制使得对象可以脱离程序的运行而独立存在。
对象的序列化(Serialize)指将一个Java对象写入IO流中,
与此对应的是,对象的反序列化(Deserialize) 则指从IO流中恢复该Java对象。
如果需要让某个对象支持序列化机制,则必须让它的类是可序列化的(serializable)。
为了让某个类是可序列化的,该类必须实现如下两个接口之一:
Java中很多类已经实现了Serializable,该接口是一个标记接口,实现该接口无须实现任何方法,它只是表明该类的实例是可序列化的。
所有可能在网络上传输的对象的类都应该是可序列化的,否则程序将会出现异常。
Java应用中最常见的bug就是空值异常。
在Java 8之前,Google Guava引入了 Optionals 类来解决 NullPointerException,从而避免源码被各种null检查污染,以便开发者写出更加整洁的代码。
Java 8 将Optional加入了官方库。
Optional仅仅是一个容易存放T类型的值或者null的类。它提供了一些有用的接口来避免显式的null检查,可以参考Java 8官方文档了解更多细节。
修饰符 | 返回值类型 | 方法 | 说明 |
|---|---|---|---|
public static | Optional | of(T value) | 创建一个容器,不能为空,否则报空指针异常 |
public static | Optional | ofNullable(T value) | 创建一个容器,可以包含null |
public | T | get() | 取容器里面的值,如果为空会抛出 NoSuchElementException |
public | boolean | isPresent() | 判断容器中是否存在对象 |
public | void | ifPresent(Consumer<? super T> consumer) | 如果容器中存在对象,则执行 consumer |
public | Optional | filter(Predicate<? super T> predicate) | 筛选 |
public | Optional | map(Function<? super T, ? extends U> mapper) | 取容器对象中的属性 |
public | T | orElse(T other) | 如果对象存在,则输出,对象不存在,则返回 other |
public | T | orElseGet(Supplier<? extends T> other) | 如果对象存在,则输出,对象不存在,则返回 other |
public | T | orElseThrow(Supplier<? extends X> exceptionSupplier) | 若是对象不存在,则抛出异常 |