2015-08-27 回答
一、简单介绍
在我们用框架编程的过程中,经常不用太关注多线程问题,这是因为例如servlet和rmi(remote method invocation,远程方法调用),rmi使得代码能够调用其他jvm中的运行的对象。这些框架负责解决一些细节问题,例如请求管理、线程创建、负载均衡,并在正确的时刻将请求分发给正确的应用程序组件。编写servlet的开发人员不需要了解有多少请求在同一时刻要被处理,也不需要了解套接字的输入流或输出流是否被阻塞。当调用servlet的service方法来响应web请求时,可以以同步方式来处理这个请求,就好像它是一个单线程程序。这种方式可以简化组件的开发,并缩短掌握这种框架的学习时间,但我们想学好编程,还是需要学习并发编程
1、编程的一些原则
在编写并发应用程序时,一种正确的编程方法就是:首先使代码正确运行,然后再提高代码的速度。即便如此,最好也只是当性能测试结果和应用需求告诉你必须提高性能,以及测量结果表明这种优化在实际环境中确实能带来性能提升时,才进行优化
2、活跃性问题
多线程中提到的活跃性问题,指的就是让线程处理死锁或活锁,就是各个线程阻塞不执行,当某个操作无法继续执行下去时,这样就导致了活跃性问题
平时编程中应该怎样做到这句话?:框架通过在框架线程中调用应用程序代码将并发性引入到程序中。在代码中将不可避免地访问应用程序状态,因此所有访问这些状态的代码路径都必须是线程安全的
3、一般并发错误的修复方法
如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误。有三种方式可以修复这个问题:
(1)不在线程之间共享该状态变量
(2)将状态变量修改为不可变的变量
(3)在访问状态变量时使用同步
4、线程安全类和线程安全程序
完全由线程安全类构成的程序并不一定就是线程安全的,而在线程安全类中也可以包含非线程安全的类
二、线程安全性
当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的
1、无状态对象
一个无状态的servlet
[java] view plain copy
import java.math.biginteger;
import javax.servlet.*;
import net.jcip.annotations.*;
@threadsafe
public class statelessfactorizer extends genericservlet implements servlet {
public void service(servletrequest req, servletresponse resp) {
biginteger i = extractfromrequest(req);
biginteger[] factors = factor(i);
encodeintoresponse(resp, factors);
}
}