进程、线程、锁

进程

一个计算机程序的运行实例,包含了需要执行的指令:

有自己独立的空间,包含程序内容和数据;

不同进程的地址空间是互相隔离的;

进程拥有各种资源和状态信息,包含打开的文件,子进程和信号处理; 

进程使用类:java.lang.Process和java.lang.ProcessBuilder 

线程

表示程序的执行流程,是CPU调度执行的基本单位;

线程有自己的程序计数器、寄存器、堆栈和帧。 

同一个进程中的线程共用相同的地址空间,相同共享进程锁拥有内存和其他资源。

线程使用类:java.lang.Thread

进程状态

创建、就绪、运行、阻塞、终止。 

线程主要有两种方式实现:

继承Thread、实现Runnable;其主要逻辑都是实现Run()函数,

Thread可以直接通过start启动线程;

Runnable就必须新建一个Thread对象进行执行start进行启动线程 

wait() notify() notifyAll()方法进行使线程休眠或者唤醒。

注意:对象wait()将当前线程放入,该对象的等待池中,线程A对用了B对象的wait()方法,线程A进入B对象的等待池,并且释放对线程B的锁

(这里线程A必须只有B的锁,所以调用的代码必须在synchronized修饰下,否则直接抛出异常)线程重新执行需要外部唤醒。 

sleep()是线程休眠一段时间后线程自动继续执行逻辑,休眠过程中不释放对象锁,线程监控状态一直存在; 

 java两种锁机制synchronized和Lock

synchronized是在JVM层面上实现的,synchronized在锁定时如果方法块抛出异常,JVM会自动将锁释放掉,不会因为出了异常没有

 释放锁造成线程死锁。

注意:synchronized作用在方法上时,锁住的便是对象实例(this);

synchronize作用在静态方法锁住的便是对象对应的Class实例,因为Class数据存在于永久带, 因此静态方法锁相当于对该类的一个全局锁;

synchronized作用于某个对象实例时,锁住的便是对应的代码块;

Lock的锁是通过代码实现的,出现异常时必须在finally将锁释放掉,否则将会引起死锁。

一般使用ReentrantLock类作为锁,多个线程中必须要使用一个ReentrantLock类作为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()

和unlock显示指出。所以一般会在finally块中写unlock以防死锁。

Condition 方法与wait、notify和notifyall方法类似,分别命名为await、signal、和signalAll

某个线程在等待一个锁的控制权的这段时间需要中断,

需要分开处理一些wait-notify,ReentrantLock里边的Condition应用、能够控制notify那个线程

具有公平锁功能,每个到来的线程都将排队等候。 

线程安全

再多线程环境下,不管什么时候执行同一段代码得到的结果都是确定的,即线程安全;

线程池主要用ThreadPoolExcutor函数,通过定义线程池的核心池大小, 最大线程数,通过实现Runnable接口的

线程交由线程池执行。

常用函数说明

sleep(long millis):在指定的毫秒数内让当前正在执行的线程休眠

join():指等待线程终止。

join是Thread类的一个方法,启动线程后直接调用,即join的作用是:等待该线程终止,这里需要理解的就是该线程是指的

主线程等待子线程的终止。也就是在子线程调用了join方法后面的代码只有等到子线程结束了才能执行。

yield():暂停当前正在执行的线程对象,并执行其他线程。

使用yield的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield达到让步目的,

因为让步的线程还有可能被线程调度程序再次选中。

setPriority():更改线程的优先级

interrupt():中断每个线程,这种结束方式比较粗暴,如果线程打开了每个资源还没来得及关闭也就是run

方法还没有执行完就强制结束线程,会导致资源无法关闭

sleep和yield的区别

sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;

yield只是使当前线程重新回到可执行状态,所以执行yield的线程有可能在进入到可执行状态后马上又被执行。 

原文地址:https://www.cnblogs.com/tflike/p/9504284.html