有一个下载方法,如果第一个人在下载,第二个人来了就提示他有人正在下载.
请问这个功能如何实现.我定义了一个全局变量设为false,
如果有人操作了.变为true,
方法里判断此变量为true的话,就提示有人下载
请问这种做法对吗
请问这个功能如何实现.我定义了一个全局变量设为false,
如果有人操作了.变为true,
方法里判断此变量为true的话,就提示有人下载
请问这种做法对吗
解决方案 »
- 求助Java调用C#WebService
- java.net.SocketException: Socket closed
- hibernate的.lang.NullPointerException错误
- 为何<%=%>无法在事件中用,高手看看
- struts 中怎么连MYSQL数据库 怎么用啊谢谢了
- 请问struts能取代ejb吗
- Apache的Axis和SOAP有什么区别?
- 再放100分!!!oracle乱字符问题
- 普通java代码如何调用hibernate4.0 实现annotation
- jsp水晶报表问题
- 求struts1+hibernate分页
- hibernate如何實現一個對象映射數據表的多行
建议用一个同步方法+全局静态对象!
就像xblue3说的一样,flag就永远都是true了。
可是我又不知道他说的全局静态对象怎么个写法。mengweilil说的流量监测,我就更不太会了。dengfeiling说的用session监听。
session监听一般不是用来统计在线人数的么,怎么用到我这里呢?
不管客户端是不是掐掉不下载,servlet方法总要走完吧?
当然也要catch expection里面也要重置
如果为false,先高成true,可以进行下载.下载完成后高为false.
如果为true,直接输出提示.这有什么难的?static Boolean flag = false;
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { synchronized(flag){
if(!flag){
flag = true;
try{
response.reset();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment; filename=你的文件名");
//输入文件内容
//关闭输出
}catch(Exception e){}
flag = false;
}
else{
response.reset();
response.setContentType("text/html");
response.getWriter().println("你来迟了,兄弟,先玩一会再来吧.");
}
}
}
<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"
buffer="16kb" autoFlush="true" isThreadSafe="true" session="false"
import="java.util.concurrent.locks.Lock,java.util.concurrent.locks.ReentrantLock"
%><%!
private final Lock idleLock = new ReentrantLock();
%><%
if (idleLock.tryLock()) {
try {
//下面的 for 用以模拟耗时的下载过程
for (int i = 0; i < 100;) {
out.println(++i + "% ");
out.flush();
Thread.sleep(160L); //模拟下载过程的耗时
}
} finally {
idleLock.unlock();
}
} else {
%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SynAccessPage</title>
</head>
<body>
<h1>现在不能处理您的下载请求,请稍后再试!</h1>
</body>
</html>
<%
}
%>
我晕,他那个是对锁的开与关进行判断的方法!!!!参考下这个http://blog.chinaunix.net/u/31357/showart_288005.html
你自己开两个实例同时运行看看那个锁还有个P用,如果连这点都不明白就不要来讨论了.
而是要等待原来那人线程的结束,根本不会立即跳到else那里执行提示.所以你的程序根本没有实际意义.
互斥对象.用显式锁还是用同步语块作用是一样,在java并发包开发过程中我虽然没有参与开发,但我为他们澄清过线程原语.
假如
class ServletTest implements Runnable{
private final Lock lock = new ReentrantLock();
public void run(){
if(lock.tryLock()){
System.out.println("enter.......");
try{
Thread.sleep(10000);
}
catch(Exception e){}
finally{
lock.unlock();
}
}else{
System.out.println("waiting.......");
}
}
}因为lock不是static的,所以它只能防止同一实例的多个线间的互斥:public class MainTest {
public static void main(String[] args) throws Exception{
ServletTest st1 = new ServletTest();
new Thread(st1).start();
new Thread(st1).start();
}
}
这两个线程访问的是同一 ServletTest st1的方法,所以那个锁起作用了.结果是:
enter.......
waiting.......但如果是两个实例,每个实例是不同的锁,所以不会互斥:
public class MainTest {
public static void main(String[] args) throws Exception{
ServletTest st1 = new ServletTest();
ServletTest st2 = new ServletTest();
new Thread(st1).start();
new Thread(st2).start();
}
}
结果是:enter.......
enter.......只要改成static的就可以保证多个实例间的互斥.
另外servlet规范没有规定是一个实例还是多个实例服务,事实上大多数容器在空间的时候是一个实例,繁忙的时候就是多个实例,而且再空闲连一个实例
都销毁了,需要的时候再创建,可以在init和destory中打印消息就以看出在服务启动后,servlet会不断被创建和销毁,并不是一直生成在那儿的.所以必须保证多实例间互斥才能保证同一时刻只有一个用户访问.
而且也没有限制普通的servlet是一个实例还是多个实例来服务.事实上大多数容器中,对普通的servlet来说,如果你用同一个servet
类做多个url-mapping你就知道它是多个实例了.它不是用一个实例来服务所有的url-mapping,而是每个实例对应一个mapping.
container must use only one instance per servlet declaration. However, for a serv-
let implementing the SingleThreadModel interface, the servlet container may
instantiate multiple instances to handle a heavy request load and serialize requests
to a particular instance.
由于一个Servlet声明中只能有一个url-mapping标签,所以你后面说的一部分我是赞同的。
偶是菜鸟不知道这样可以不可以.....
所以说一个servlet在很多情况下会有多个实例.你的那个文档应该是没有及时更新.比如JDBC从1.0到3.0中大对象的例子都是错误的,都是从上一版COPY过来的.2.4的主要更新中明确说明:
改为Schema后主要加强了两项功能:
(1) 元素不依照顺序设定
(2) 更强大的验证机制
主要体现在:
a.检查元素的值是否为合法的值
b.检查元素的值是否为合法的文字字符或者数字字符
c.检查Servlet,Filter,EJB-ref等等元素的名称是否唯一
2.新增Filter四种设定:REQUEST、FORWARD、INCLUDE和ERROR。
3.新增Request Listener、Event和Request Attribute Listener、Enent。
4.取消SingleThreadModel接口。当Servlet实现SingleThreadModel接口时,它能确保同时间内,
只能有一个thread执行此Servlet。
5.<welcome-file-list>可以为Servlet。
6.ServletRequest接口新增一些方法。
public String getLocalName()
public String getLocalAddr()
public int getLocalPort()
public int getRemotePort() 取消SingleThreadModel是它专门作为新特性来阐述的.
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8"); if (getFlag()) {
g_1(request, response);
} else {
g_2(request, response);
}
} protected void g_1(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
try {
//
} finally {
out.close();
flag = true;
}
} protected void g_2(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
try {
//
} finally {
out.close();
}
} private static synchronized boolean getFlag() {
if (flag) {
flag = false;
return true;
} else {
return false;
}
}
private static boolean flag = true;
我认为servlet如果没有配多个MAPPING(我没配过),没有负载平衡,分布等
那么它在一个容器里面默认应该只有一个实例,除非实现SingleThreadModel接口我用JProfile做了下小实验,在本机中访问同一个 servlet 只有一个实例,这个实例其实是多线程的不过我觉得应该按照axman说的 设成 static 比较好
23 楼代码实际运行试试(按你说的把 idleLock 声明成静态的),我拿 Tomcat6.0.18 测试没问题。
是你弄错了,JSP 中 page 指令 isThreadSafe 属性的默认值就是 true,即加不加 isThreadSafe="true" 都一个样,我这里加上只是为了强调一下此处的默认设置。而 isThreadSafe="false" 才是同一时间只允许一个线程执行此 JSP 页。