1、进程与线程的关系
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动, 进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
进程有独立的地址空间
进程有单独的地址空间,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。
文本区域存储处理器执行的代码;
数据区域存储变量和进程执行期间使用的动态分配的内存;
堆栈区域存储着活动过程调用的指令和本地变量。
线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间
一个线程包含以下内容。
一个指向当前被执行指令的指令指针;
一个栈;
一个寄存器值的集合,定义了一部分描述正在执行线程的处理器状态的值;
一个私有的数据区。
2、线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,那么就是线程安全的。 一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
3、关于线程安全
1) 常量始终是线程安全的,因为只存在读操作。
2) 每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源(共享堆内存)。
3) 局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
3、有状态和无状态对象
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量(成员变量)的对象 ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。其实就是有数据成员的对象。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量(成员变量)的对象。不能保存数据,是不变类,是线程安全的。具体来说就是只有方法没有数据成员的对象,或者有数据成员但是数据成员是可读的对象。
代码如下
/**
* 有状态bean,有state,user等属性,并且user有存偖功能,是可变的。 user是MVC中的M,实体类,有数据库表* 的属性和属性的setter、getter方法,可以存储数据,属于有状态;属于线程不安全。
*/
public class StatefulBean {
public int state;
// 由于多线程环境下,user是引用对象,是非线程安全的
public User user;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
/**
* 无状态bean,不能存偖数据。因为没有任何属性,所以是不可变的。只有一系统的方法操作。
* BillDao是dao层类,有一些find,add,save方法。dao本身也是单例的,属于无状态;不存在线程安全问题。
* /
public class StatelessBeanService {
// 虽然有BillDao属性,但billDao是没有状态信息的,是Stateless Bean.
BillDao billDao;
public BillDao getBillDao() {
return billDao;
}
public void setBillDao(BillDao billDao) {
this.billDao = billDao;
}
public List<User> findUser(String Id) {
return null;
}
}