在线阅读加锁的功能 或者JAVA悲观锁

我想实现一个 在线阅读 加锁的功能
就是当这个文档在阅读的时候  其他的不可以访问并且等到一个提示  这个有什么方法。
也可以理解为  我就是想用JAVA 实现 数据库的 悲观锁。

回答: 在线阅读加锁的功能 或者JAVA悲观锁

  1. class TestLock{
    	private static Map<String, String> pool = new ConcurrentHashMap<String, String>();
    	public static void main(String[] args) {
    		for(int i=0;i<5;i++){
    			new Thread(
    					new Runnable(){
    						public void run(){
    						    try {
    						    	//使用MD5,可以区分文件名不同但内容相同的文档
    								String md5Str =MD5Helper.getFileMD52(new File("d:"+File.separator+"a.doc"));
    								if(pool.get(md5Str)==null){
    									pool.put(md5Str, md5Str);
    								}
    								//同步 保证同一份文档 仅允许同一个用户阅读
    								synchronized (pool.get(md5Str)) {
    									 System.out.println(Thread.currentThread().getName()+"正在阅读...");  
    									//移除
    									pool.remove(md5Str);
    									System.out.println(Thread.currentThread().getName()+"阅读结束!!!...");  
    								}
    						    } catch (IOException e) {
    								e.printStackTrace();
    							}
    						    }  
    					}
    			
    			).start();
    		}
    	  
    	}
    }
    class MD5Helper{
    	public static String getFileMD52(File file) throws IOException {
    		String res = "";
    		ByteArrayOutputStream out = new ByteArrayOutputStream();
    		FileInputStream in = null;
    		try {
    			in = new FileInputStream(file);
    			byte[] inb = new byte[1024];
    			while (in.read(inb) != -1) {
    				out.write(inb);
    			}
    		} catch (FileNotFoundException e1) {
    			e1.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}finally{
    			if(in!=null){
    				in.close();
    			}
    			in = null;
    		}
    		try {
    			MessageDigest md5C = MessageDigest.getInstance("MD5");
    			byte[] b = md5C.digest(out.toByteArray());
    			res = byteArrayToHexString(b);
    		} catch (final NoSuchAlgorithmException e) {
    		}finally{
    			out.close();
    			out = null;
    		}
    		return res;
    	}
    	
    	public static String byteArrayToHexString(byte in[]) {
    		byte ch = 0x00;
    		int i = 0;
    		if (in == null || in.length <= 0)
    			return null;
    
    		String pseudo[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
    				"A", "B", "C", "D", "E", "F" };
    		StringBuffer out = new StringBuffer(in.length * 2);
    
    		while (i < in.length) {
    			ch = (byte) (in[i] & 0xF0); // Strip off high nibble
    			ch = (byte) (ch >>> 4);
    			// shift the bits down
    			ch = (byte) (ch & 0x0F);
    			// must do this is high order bit is on!
    			out.append(pseudo[(int) ch]); // convert the nibble to a String
    											// Character
    			ch = (byte) (in[i] & 0x0F); // Strip off low nibble
    			out.append(pseudo[(int) ch]); // convert the nibble to a String
    											// Character
    			out.append(" ");
    			i++;
    		}
    		String rslt = new String(out);
    		rslt = rslt.trim();
    		return rslt;
    	}
    }
    
    
    

找个牛人解释java悲观锁和乐观锁!

  1. Q
    找个牛人解释java悲观锁和乐观锁!
  2. A
    悲观锁,就是不管是否发生多线程冲突,只要存在这种可能,就每次访问都加锁。

    乐观锁,就是通过标记值控制,每次操作前通过标记值判断是否是最新内容,最新内容就可以操作,不是最新的就继续循环判断标记值,直到是最新类容。

    在大量冲突发生时,悲观锁的锁消耗大,乐观锁的读取次数会多。

乐观锁和悲观锁分别是什么 区别在哪里?

  1. Q
    乐观锁和悲观锁分别是什么 区别在哪里? 求达人解释!!!
  2. A
    当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。锁有两种:悲观锁和乐观锁。悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。与悲观锁相反,乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁可以用较大的锁粒度获得较好的并发访问性能。但是如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。这说明在乐观锁环境中,会增加并发用户读取对象的次数。
    从数据库厂商的角度看,使用乐观的页锁是比较好的,尤其在影响很多行的批量操作中可以放比较少的锁,从而降低对资源的需求提高数据库的性能。再考虑聚集索引。在数据库中记录是按照聚集索引的物理顺序存放的。如果使用页锁,当两个用户同时访问更改位于同一数据页上的相邻两行时,其中一个用户必须等待另一个用户释放锁,这会明显地降低系统的性能。interbase和大多数关系数据库一样,采用的是乐观锁,而且读锁是共享的,写锁是排他的。可以在一个读锁上再放置读锁,但不能再放置写锁;你不能在写锁上再放置任何锁。锁是目前解决多用户并发访问的有效手段

Office 在线阅读功能 ??

  1. Q
           Office 在线阅读功能,能兼容2003及以后版本,然后可以兼容IE,火狐,chrome三大浏览器,tomcat发布,Java开发环境,有哪位大神做过了,给个解决方案,看到有几家公司在卖这种中间件,感觉做的还不错,但是目前公司不会购买!谢谢大家了....
  2. A
    参见
    http://www.microsoft.com/getsilverlight/office/zh-cn/how.html

求 累似百度文库在线阅读的解决方案

  1. Q
    求 累似百度文库在线阅读的解决方案

    要求
    1,可阅读word,excel,pdf,txt 等文件格式

    2,可靠性要好,可以推荐收费的软件,应用在winodws java 环境

    我现在用的是 jodconverter 转成pdf  在用 swftools 转成 swf 用 flexpaper实

    现在线阅读,可是这样有个问题,就是swftools 转 swf时,稍复杂的一点的文件

    就换失败了。。。

    求帮助啊。。。提供一个优化方案或者,,其他的解决方案都行,,收费的也可以
  2. A
    用openoffic转成pdf。
    用pdf2swf把pdf转成swf,转换的时候注意命令,把每一页都生成一个swf文件就好了。
    用pdfreader把pdf的第一页截取一帧当预览图。

    阅读器试试 flexpaper_flash.js。

    我的文档库系统运行一年多了从么有发现过你说的pdf太负责就转换失败的。

【电子书】blackberry 官方教程可在线阅读和下载

  1. Q
    分享一个好消息给大家,BlackBerry 官方教程在陆续发布中,都是黑莓专家写的,可以在线阅读,也可下载到本地,蛮不错的,这些文档都很详细,很值得一读,现有列表如下
    # BES 服务推送机制分析
    # BlackBerry Java 开发环境安装及入门
    # BlackBerry SDK 介绍
    # BlackBerry Widget 开发入门
    # BlackBerry Widget 开发中级篇
    # BlackBerry 用户界面开发实例
    # BlackBerry代码签名工具申请及安装介绍
    # 如何将MIDlet应用移植到BlackBerry
    # 使用BlackBerry Transcoder API 集成第三方加密方案
    # BlackBerry 网络连接编程
    # BES_推送应用实例演示与分析
    # BlackBerry 照相编程
    # BlackBerry 应用和MIDlet之间的交互
    # BlackBerry视频录制编程

    教程地址为:

    支持偶的留下足迹哦,不要让文章沉下去哦
  2. A
    还是不错的

求在线阅读类网站架构与实施方案

  1. Q
    如题!
    像京东商城或者豆瓣类的在线读书的网站架构是什么样的?像这种大量图书从纸质到数字化然后到实现网站在线阅读的实施流程或者实施方案,希望高手指点。或者一起探讨一番。
  2. A
    我看他们有的说是将word等格式转化为pdf格式展现。帮顶。

《我的第一本C++书》在线阅读:第一张 1.4 如何学好C++

  1. Q
    当当网推荐率96.9%——
    更多在线阅读在这里

    .4  如何学好C++
    既然C++如此强大,那么如何学好C++呢?
    每个C++初学者都会问这个问题。虽然这个问题没有统一的答案,但是作为一个C++世界的导游,我可以介绍一些经验和教训给大家,让大家少走弯路,沿着正确的方向前进,轻松愉快地完成C++世界的奇妙之旅。
    1.4.1  将自然语言转换为C++程序设计语言
    C++是一门程序设计语言,有着语言的基本特征,我们可以像学习普通语言一样来学习C++。
    语言,是用来描述和表达现实世界的,编程语言也不例外。为了描述现实世界的事物,我们需要一些名词。这些名词在C++中就是数据类型和用数据类型表达的数据。为了表达事物之间的关系,可以将各个事物连缀成句子,这些句子在C++中就是表达式。将多个句子通过一定的逻辑关系组合起来,就可以形成一篇文章。同样,在C++中通过一定的逻辑控制将多个表达式组合起来就形成了程序。通过C++编程语言和自然语言的对比,我们可以轻松地理解C++程序的含义。C++是描述现实世界的编程语言,编写程序的过程,是将自然语言翻译成C++语言的过程,如此而已。比如,在自然语言中,我们可以这样来描述一件事情:有个男孩叫小张,有个女孩叫小芳。男孩向女孩示爱。女孩对男孩进行考察,如果男孩有房又有车,则与男孩交往;如果没有,则与男孩拜拜。翻译过程可以参考图1-4。
      
    图1-4  编程就是把自然语言翻译成C++语言
     
    如果把自然语言翻译成C++语言,则是这样的:
    //有个男孩叫小张
    Boy XiaoZhang;
    //有个女孩叫小芳
    Girl XiaoFang;

    //男孩向女孩示爱
    XiaoZhang.ShowLoveTo(XiaoFang);
    //女孩对男孩进行考察
    //如果男孩有房又有车
    if(XiaoZhang.HasHouseAndCar() )
    {
        //女孩与男孩交往
        XiaoFang.SayHiTo(XiaoZhang);
    }
    else // 如果没有
    {
        //则与男孩拜拜
        XiaoFang.SayByeTo(XiaoZhang);
    }
    通过将自然语言翻译成C++编程语言,就形成了一段C++程序。只要我们会说话,就会用C++编程。C++编程,就这么简单!
    虽然C++语言是从C语言发展而来的,但是可以认为C++是一门全新的独立的编程语言,它并不依赖于C语言。学习C++不必掌握C语言,但学好了C++语言,自然就掌握了C语言。
    什么是程序设计语言
    程序设计语言,通常简称为编程语言,它是一组用来定义计算机程序的语法规则,是一种标准化的交流技巧。利用程序设计语言,程序员能够准确地定义计算机需要使用的数据,并精确地定义在不同情况下所应当采取的行动,让计算机完成特定的任务。
    程序设计语言是一套包含语法、词汇和含义的正式规范。这些规范通常分成4个部分。
     数据成分:用以描述程序中所涉及的数据。
     运算成分:用以描述程序中所包含的运算。
     控制成分:用以表达程序中对运算流程的控制。
     传输成分:用以表达程序中数据的传输。
    按语言级别,程序设计语言可以分为低级语言和高级语言。低级语言包括字位码、机器语言和汇编语言。其特点是与特定的机器有关,效率高,但使用复杂、烦琐、费时、易出差错。其中,字位码是计算机可直接理解的唯一语言,但由于它是一连串的字位,复杂、烦琐、冗长,几乎无人直接使用。机器语言是表示成数码形式的机器基本指令集,是操作码经过符号化的基本指令集。汇编语言把机器语言中的地址部分符号化,并进一步包括了宏构造。
    高级语言是比低级语言更接近于待解决问题的表示方法,其特点是在一定程度上与具体机器无关,易学、易用、易维护。把高级语言程序翻译成低级语言程序,一个高级语言程序单位对应多条机器指令,产生的目标程序性能比低级语言程序低。C++语言就是一种高级程序设计语言。
    大多数被广泛使用或经久不衰的程序设计语言,都有专门的标准化组织,负责规范及发布该语言的正式定义,并讨论扩展或贯彻现有的定义。
    1.4.2  “多读多写”是学好C++的不二法门
    还记得当年我们学习外语的时候,老师总是教导我们要“多听多说多读多写”。同样,学习C++也强调“听说读写”。对于编程语言而言,虽然没有“听”和“说”,但是“多读”和“多写”却同样是学好C++的不二法门。
    1. 多读
    多读就是强调多阅读和学习别人的优秀代码,特别是一些优秀的开源产品的源代码。通过阅读这些源代码,不仅可以学习具体的语言知识、开发技术,还可以从中学习设计思想、编程风格等。向高手学习,是成为高手的唯一途径。
    2. 多写
    多写,就是多多地进行开发实践。编程是一门技艺,它来自于实践,光纸上谈兵是无法学好编程的。多写包括很多方面,比如,在开发环境中完成书本上的例子程序,重新实现网络上的例程,开发实现一些小程序等。多读的目的只是学习别人的知识和经验,多写的目的是将别人的知识和经验内化为自己的知识和经验。同时,通过多写可以发现很多在阅读技术书籍、阅读程序代码时隐藏的问题。通过自己编写程序、调试程序,可以获得宝贵的第一手开发经验,培养自己的动手能力,从而成为一个真正的高手。
    1.4.3  和Google做朋友
    在开发实践中,与其说程序是编出来的,倒不如说是搜出来的。如果遇到一个语法上的细节问题就可以用Google搜索关于C++的教程;如果遇到函数使用上的问题,就可以用Google搜索这个函数的文档;如果遇到常见的开发任务,就可以用Google搜索已有的示例代码。甚至当遇到程序中的疑难杂症时,都可以用Google搜索有没有人遇到相同的问题。总之,编程开发离不开Google。网络就像一个大金矿,而Google就是采矿机器。善用Google、和Google做朋友,可以帮助我们充分利用丰富的网络资源来学好C++,用好C++。
     
    好好学习:学会使用Google
    你会使用Google吗?
    这还用问吗?Google谁不会用啊!
    你真的会使用Google吗?
    所谓搜索,就是“使用正确的工具和正确的方法寻找正确的内容”。
    这里的工具,就是我们使用的搜索引擎。Internet只有一个,而搜索引擎则有许多个。虽然各个搜索引擎各有特长,但是对程序员来说,Google是最合适的工具。至于原因,我就不在这里啰嗦了,大家可以自己去Google。
    掌握搜索引擎的使用技巧可以让我们轻松地在茫茫大海中捞出我们需要的那根针。例如,可以使用双引号来表示某个必须包含的关键词,也可以使用OR或者AND等逻辑运算连接多个关键词,从而更准确地表示我们想要的内容,甚至可以使用site标记,将搜索范围限定在某个网站之内。学习和掌握搜索引擎的使用技巧可以帮助我们更好地使用搜索引擎,更快、更准地找到我们想要的内容。
  2. A
    陈良乔还没肃清么。
    咋不注册马甲吹人宇科学呢。

关于hibernate的悲观锁

  1. Q
      请问各位高手,我们在进行写hibernate悲观锁的时候,如何让一条记录在没有被锁住之前没有锁图标(这个就是自己定义的一张图片),在有人操作这条记录的时候,这条记录自动变成了有锁的图标。请各大位高手说一下,谢谢了。
  2. A
    建议不要用hibernate悲观锁实现你的需求。
    你需要的是一个支持长事务的锁(客户端和服务端是多次http请求响应)。hibernate悲观锁不适合。试想一下:一个用户正准备修改一条记录,死机了。这个记录就永远不能改了。除非手工在数据控制台解除这个锁。
    所以,你们应该自己在应用程序级别,不是数据库级别,实现这个长事务的锁。加入超时自动解锁或管理员手工解锁的功能。

这个java业务锁怎么实现?

  1. Q
    在网上看到一个问题,是想问一个java业务锁的问题;
    方法逻辑伪代码:
    private List<权限> 获取所有权限(String 权限组名称){
         if(cache.get(权限组名称)!=null){
             return (List<权限>)cache.get(权限组名称);
         }
         List<权限> 值=从数据库里读取并整理(权限组名称);
         cache.put(权限组名称,值);
         return 值;
     } 

    现在需要给这个方法添加并发锁,需求是:
     当多个线程同时进入该方法,多个权限组名称参数值相同的线程只能有一个写,多个权限组名称参数值互不相同的线程可以并发读和并发写;只要权限组名称参数值不同,多个读和多个写是可以同时存在的。
     需求目的是为了防止高并发下同一个权限组被多次触发 从数据库里读取并整理()方法 和cache.put()方法并保证高性能和数据一致。
    下面是一个网友的回答;

    public class Test2 {
        public static void main(String[] args){
            final Permission1 permission = new Permission1();
            int n = 10;
            ExecutorService pool = Executors.newFixedThreadPool(n);
      
            for (int i = 0; i < n * 5; i++) {
                final String name = String.valueOf(i % 3);
                pool.execute(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < 100; j++) {
                            System.out.println(name + " - >" + permission.getPermissions(name).toString());
                        }
                    }
                });
            }
            pool.shutdown();
        }
    }

    class Permission1 {
      
        private Map<String, ArrayList<String>> cache = new HashMap<String, ArrayList<String>>();
      
        public ArrayList<String> getPermissions(String name) {
            //1.如果缓存为null,则放入一个空对象,作为锁
            if (cache.get(name) == null) {
                cache.put(name, new ArrayList<String>());
            }
      
            ArrayList<String> list = cache.get(name);
            if (list.size() == 0) { //2.长度为0,则代表没有初始化过,当然也可以改变为其他条件
                synchronized (list) {
                    // 3.亮点在此,绝不可以将cache.get(name) 改为list,不信你试试
                    if (cache.get(name).size() == 0) {
                        cache.put(name, this.getPermissions2(name));
                    }
                }
            }
            // 4.不能直接返回list,原因在 注释3
            return cache.get(name);
      }  
        /**
         * 模拟从数据库中取除对应的
         * */
        private ArrayList<String> getPermissions2(String name) {
            System.err.println("Permission Name : "+ name);
            try {
                Thread.sleep(1000);
      
                ArrayList<String> list = new ArrayList<String>();
                String date = name + "->" + String.valueOf(new Date().getTime());
                list.add(date);
      
                return list;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }


    暂且不提这么做对不对,我有几个问题。
    请高手解惑:

    1.
     if (list.size() == 0) { //2.长度为0,则代表没有初始化过,当然也可以改变为其他条件
    这句话偶尔会报空指针异常
    2.
     System.err.println("Permission Name : "+ name);
    这句话某个相同的name会被打印不止一次。哪里有问题呢
    3.synchronized 块那里list是一个局部变量,应该是线程安全的吧。为什么要synchronized 呢
    4.
       if (cache.get(name) == null) {
                cache.put(name, new ArrayList<String>());

    有网友说这里会有java内存可见性问题,为什么?

    5.打印出来的时间大多数情况下都是一样的,是运行太快的原因,还是哪里出错了

    6.最后这么设计合不合理
  2. A

    简单说一下:
    1. 27-31行,缺锁,应该用你的cache对像锁住。假设你有多个线程并行开始,那么首先里面肯定是空的,那么大家都new,都往里放东西。估计第一个问题应该是线程安全问题导致的,但我总觉得应该不可能。
    2. 34-39,全局锁,当然不是不可以。问题是,你Load一个权限的时候,有任何的权限读取都会等这个锁,可能会有性能问题。如果你改完了我下面说的,你完全可以用List对像作为锁。
    3. getPermissions2 这个函数返回的是一个新建的ArrayList。你自己的注释中的问题3、4基本上都源于此。你代码中32行中取到的这个List,很有可能已经被你这个getPermissions2中创建的ArrayList所覆盖。所以这个函数应该是用Name和AarryList同时作为参数,加到原来的ArrayList中即可。

    不好意思点错了。
    您说的第一点我明白了。
    关于第三点,不太明白。您所说“代码中32行中取到的这个List,很可能已经被这个getPersmission2()中创建的ArrayList覆盖” 是害怕在这里ArrayList<String> list = new ArrayList<String>();就替换还是getPermission2()执行后覆盖。前者都是方法中的局部变量互相应该不相干啊,后者的话,getPermission2模拟的是从数据库里拿权限名字。这个权限名字不是一样吗,覆盖了不也一样吗。请指点。
    还有第二点,您所说的全局锁。我用的不是锁list的吗
    我这么说吧, 线程A,拿了个权限PA对应的是LISTA;因为你是在锁外面拿的变量,所以在锁的代码块里面,MAP里面的东西有可能被线程B的getPermission2中new出来的东西所覆盖,假设叫ListB。权限的名字一样,但是你List是两个完全不同的List。所以你在线程B里对map里的做的任何操作,都不会影响到本地变量中引用的List实例。所以你才会有你的第三,第四个问题。

    我觉得你最重要的一点是可能没有搞清楚对像实例和对像引用的关系。本地的list是对像引用,而你在很多个地方实例化了这个List对像实例。自己画个时序图再好好的理解理解。