精华内容
下载资源
问答
  • java finalize在高并发应用中安全删除文件的应用finalize的作用finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。finalize()与C++中的析构函数不是对应的。...

    java finalize在高并发应用中安全删除文件的应用

    finalize的作用

    finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。

    finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性

    不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。其原因可见下文[finalize的问题]

    2. finalize的问题

    一些与finalize相关的方法,由于一些致命的缺陷,已经被废弃了,如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法

    System.gc()与System.runFinalization()方法增加了finalize方法执行的机会,但不可盲目依赖它们

    Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行

    finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行

    对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的

    finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)

    3. finalize的执行过程(生命周期)

    (1) 首先,大致描述一下finalize流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。

    (2) 具体的finalize流程:

    对象可由两种状态,涉及到两类状态空间,一是终结状态空间 F = {unfinalized, finalizable, finalized};二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}。各状态含义如下:

    unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的

    finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行

    finalized: 表示GC已经对该对象执行过finalize方法

    reachable: 表示GC Roots引用可达

    finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达

    unreachable:对象不可通过上面两种途径可达

    示例伪代码:

    public class ParquetFile {

    //部分属性略

    ​private int refCnt = 1;//引用计数器

    public synchronized void addRefCoun() {

    refCnt = refCnt + 1;

    }

    public synchronized void subRefCoun() {

    refCnt = refCnt - 1;

    }

    public synchronized int getRefCoun() {

    return refCnt;

    }

    @Override

    public void finalize() {

    //在此删除文件

    }

    }

    public class GcTest{

    在此只是测试用,在多线程应用中当文件没有被引用时即引用计数器为0时,系统GC时即会调用对象的finalize()方法,实现安全的删除文件。

    public static void main(String[] args) throws Exception {

    ParquetFile fileRef = new ParquetFile("test.par");

    ParquetFileManager.getInstance().addRef(fileRef);

    //someint proce code

    ParquetFileManager.getInstance().removeRef("test.par")

    System.gc();

    Thread.sleep(5000);

    }

    }

    展开全文
  • Java 并发编程专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Java 并发编程 BlockingQueue 阻塞队列是什么 队列(Queue),是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入...

    专栏原创出处:github-源笔记文件 github-源码 ,欢迎 Star,转载请附上原文出处链接和本声明。

    Java 并发编程专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Java 并发编程

    BlockingQueue 阻塞队列是什么

    • 队列(Queue),是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
    • 阻塞与非阻塞,关注的是程序在等待调用结果(消息,返回值)时的状态.
      • 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
      • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

    阻塞队列(BlockingQueue 接口)是一个支持阻塞的插入和移除方法的队列,主要采用锁实现。

    • 支持阻塞的插入方法 : 意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满
    • 支持阻塞的移除方法 : 意思是在队列为空时,获取元素的线程会等待队列变为非空

    BlockingQueue 接口相关方法说明

    抛出异常的操作方法

    • add 方法:插入列尾,当队列满时,会抛出 IllegalStateException 异常。
    • remove 方法:返回并移除队列头,当队列为空时,从队列里获取元素会抛出 NoSuchElementException 异常。
    • element 方法:返回队列头(不移除),当队列满时,会抛出 IllegalStateException 异常。

    返回特殊值的操作方法

    • offer 方法:插入列尾,成功返回 true。
    • poll 方法:返回并移除队列头,如果没有元素则返回 null。
    • peek 方法:返回队列头(不移除),如果没有元素则返回 null。

    一直阻塞的操作方法

    • put 方法:插入列尾,当队列满时阻塞等待,直到队列可用或者响应中断退出。
    • take 方法:返回并移除队列头,当队列为空时阻塞等待,直到队列可用或者响应中断退出。

    方便记忆的规律:

    • put 和 take 分别尾首含有字母 t。【他们会等啊】(t 打头)
    • offer 和 poll 都含有字母 o。【哦,没异常啊】(o 打头)

    BlockingQueue 接口的实现类有哪些

    类图关系-BlockingQueue

    JDK1.8 提供了 7 个阻塞队列,如下:

    • ArrayBlockingQueue : 数组结构组成的有界阻塞队列
    • LinkedBlockingQueue : 链表结构组成的有界阻塞队列
    • PriorityBlockingQueue : 支持优先级排序的无界阻塞队列
    • DelayQueue : 支持延时获取元素的无界阻塞队列
    • SynchronousQueue : 不存储元素的阻塞队列
    • LinkedTransferQueue : 由链表结构组成的无界阻塞队列
    • LinkedBlockingDeque : 由链表结构组成的双向阻塞队列

    下面章节将一一介绍各个实现类的特性、实现原理、注意事项、应用场景

    ArrayBlockingQueue-数组、有界

    一个用数组实现的有界阻塞队列。此队列按照先进先出 (FIFO) 的原则对元素进行排序。

    • 特性:

      • 支持公平、非公平选择
    • 实现原理

      • 内部维护一个 Object[] items 数组
      • 使用 ReentrantLock 锁、 2 个 Condition 条件(notEmpty、notFull)完成并发访问
      • 对该队列的数组操作使用 ReentrantLock 加锁解锁,阻塞条件使用 Condition 等待通知机制完成

    LinkedBlockingQueue-链表、有界

    一个用链表实现的有界阻塞队列。此队列的默认和最大长度为 Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。

    实现原理:

    • 内部维护链表的头节点、尾节点
    • 使用 ReentrantLock putLock 、Condition notFull 管理入队操作
    • 使用 ReentrantLock takeLock 、Condition notEmpty 管理出队操作
    • 完全的生产者消费者模式的实现

    PriorityBlockingQueue-优先级排序、无界

    一个支持优先级的无界阻塞队列。默认情况下元素采取自然顺序升序排列。也可以自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来对元素进行排序。需要注意的是不能保证同优先级元素的顺序。

    实现原理:

    • 内部维护一个 Object[] items 数组
    • 使用 ReentrantLock lock 、Condition notEmpty 管理入队出队操作(因为无界,无需 notFull 条件)
    • 入队时,判断是否需要扩容,插入数组(重新排序(最小堆))
    • 出队时,移除下标为 0 的数据(列头),重新排序

    DelayQueue-延时获取、无界

    一个支持延时获取元素的无界阻塞队列。队列使用 PriorityQueue 来实现。

    队列中的元素必须实现 Delayed 接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。

    实现原理:

    • 内部维护一个 PriorityQueue(支持排序的队列实现类)
    • 使用 ReentrantLock lock 、Condition available 管理入队出队操作(因为无界,无需 notFull 条件)
    • 入队时,数据添加至 PriorityQueue 队列,判断当前头节点是否等于添加的数据,如果不是唤醒出队操作
    • 出队时,for 循环自旋,取出头节点如果达到执行时间即返回,否则进入等待

    SynchronousQueue-不存储元素

    一个不存储元素的阻塞队列。每一个 put 操作必须等待一个 take 操作,否则不能继续添加元素。

    SynchronousQueue 可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身并不存储任何元素,非常适合传递性场景。SynchronousQueue 的吞吐量高于 LinkedBlockingQueue 和 ArrayBlockingQueue。

    • 特性:
      • 支持公平、非公平选择
    • 实现原理,源码解读参考 SynchronousQueue

    LinkedTransferQueue-链表、无界

    一个由链表结构组成的无界阻塞 TransferQueue 队列。相对于其他阻塞队列,LinkedTransferQueue 多了 tryTransfer 和 transfer 方法。

    方法解读:

    • transfer 方法 :可以把生产者传入的元素立刻"传输"给消费者。如果没有消费者在等待接收元素,transfer 方法会将元素存放在队列的 tail 节点,并等到该元素被消费者消费了才返回
    • tryTransfer 方法 : 用来试探生产者传入的元素是否能直接传给消费者。如果没有消费者等待接收元素,则返回 false。

    transfer 和 transfer 方法的区别: tryTransfer 方法无论消费者是否接收,方法立即返回,而 transfer 方法是必须等到消费者消费了才返回。

    LinkedBlockingDeque-链表、双向阻塞队列

    一个由链表结构组成的双向阻塞队列。所谓双向队列指的是可以从队列的两端插入和移出元素。双向队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。

    相比其他的阻塞队列,LinkedBlockingDeque 多了 addFirst、 addLast、offerFirst、offerLast、peekFirst 和 peekLast 等方法,以 First 单词结尾的方法,表示插入、获取 (peek) 或移除双端队列的第一个元素。
    以 Last 单词结尾的方法,表示插入、获取或移除双 端队列的最后一个元素。
    另外,插入方法 add 等同于 addLast,移除方法 remove 等效于 removeFirst。
    但是 take 方法却等同于 takeFirst,不知道是不是 JDK 的 bug,使用时还是用带有 First 和 Last 后缀的方法更清楚。

    应用场景

    • 生产消费者模型

    其实实际程序处理,绝大多数场景都可以抽象为,“数据源-> 数据处理-> 数据消费” 过程,把这个过程无限的组合起来就是我们的程序。

    展开全文
  • 上传前需要为目录开放权限,否则客户端上传会因为没有权限而失败 $ hadoop fs -mkdir /test #创建目录 ...$ hadoop fs -rm -r /test/jdk-8u121-docs-all #删除目录 上传下载的基础类,配置文件另写,目的是

    上传前需要为目录开放权限,否则客户端上传会因为没有权限而失败

    $ hadoop fs -mkdir /test          #创建目录
    $ hadoop fs -chmod  777 /test            #修改权限
    $ hadoop fs -rm -r /test/jdk-8u121-docs-all    #删除目录


    上传下载的基础类,配置文件另写,目的是去缓存,根据每个文件大小写数据块。而不是使用系统自己的配置,能节省空间。

    /*

     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package com.aqdog.hadoop;


    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URI;
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FileStatus;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.IOUtils;


    /**
     *
     * @author bruce
     */
    public class HadoopUtils {


        public static void uploadFileToHDFS(Configuration conf, File file, String dst) throws Exception {
            //创建一个文件系统  
            FileSystem fs = FileSystem.get(conf);
            Path srcPath = new Path(file.getAbsolutePath());
            Path dstPath = new Path(dst);
            Long start = System.currentTimeMillis();
            fs.copyFromLocalFile(false, srcPath, dstPath);
            System.out.println("size:" + file.length() + "\t Time:" + (System.currentTimeMillis() - start) + "\t" + file.getAbsolutePath());
            fs.close();
        }


        /**
         * 下载文件
         *
         * @param src
         * @throws Exception
         */
        public static void downLoadFileFromHDFS(Configuration conf, String src, File tarFile) throws Exception {
            FileSystem fs = FileSystem.get(conf);
            Path srcPath = new Path(src);
            InputStream in = fs.open(srcPath);
            OutputStream out = new FileOutputStream(tarFile);
            try {
                if (tarFile.exists() && tarFile.isFile()) {
                    tarFile.delete();
                }
                IOUtils.copyBytes(in, out, 4096, true);
            } finally {
                IOUtils.closeStream(in);
                IOUtils.closeStream(out);
                fs.close();
            }
        }


        /**
         * 遍历指定目录(direPath)下的所有文件
         *
         * @param direPath
         * @throws Exception
         */
        public static void getDirectoryFromHdfs(Configuration conf, String direPath) throws Exception {


            FileSystem fs = FileSystem.get(URI.create(direPath), conf);
            FileStatus[] filelist = fs.listStatus(new Path(direPath));
            for (int i = 0; i < filelist.length; i++) {
                FileStatus fileStatus = filelist[i];
                System.out.println("Name:" + fileStatus.getPath().getName() + "size:" + fileStatus.getLen());
            }
            fs.close();
        }
    }

    下面是测试类,可以单线程上传文件和多线程上传文件。我使用的是JDK DOC目录做的上传,大约有16000多个文件,并发后,每个文件的上传时间明显增长。

    我尝试过四种情况,顺序,50,500,不限制并发数。

    不并发的时候每个文件上传在20毫秒左右;50个并发的时候,100毫秒;500的时候2秒左右。

    不限制并发数,就是有多少个文件,起多少个线程,然后是半天没反应,有反应了就跑了几行,然后直接死了。


    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package com.aqdog;


    import com.aqdog.hadoop.HDFSUtils;
    import com.aqdog.hadoop.HadoopUtils;
    import com.aqdog.utils.StringUtils;
    import java.io.File;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map.Entry;
    import java.util.logging.Level;
    import org.junit.Test;
    import org.apache.hadoop.conf.Configuration;
    import org.apache.log4j.Logger;


    /**
     *
     * @author bruce
     */
    public class TestHadoop {
        
        static Logger log = Logger.getLogger(TestHadoop.class);
        
        public static void main(String args[]) {
           // TestHadoop th = new TestHadoop();
            //th.testByThread();
            //th.testOneThread();
            
            TestHadoop.downloadFile("/test/aaaa/ideaIU-2016.3.5.exe", new File("D:/aaaa/aaaa.exe"));
        }
        
        public void testOneThread() {
            TestHadoop.readFiles(new File("D:\\aaaa"));
            long starTime = System.currentTimeMillis();// 开始时间   
            List<T> list = new ArrayList();
            for (Entry<String, String> en : fileMap.entrySet()) {
                TestHadoop.writeFile(new File(en.getKey()), en.getValue());
            }
        }
        
        public void testByThread() {
            TestHadoop.readFiles(new File("D:\\jdk-8u121-docs-all"));
            long starTime = System.currentTimeMillis();// 开始时间   
            List<T> list = new ArrayList();
            int threadConntLimit = 500;         //限制并发数
            for (Entry<String, String> en : fileMap.entrySet()) {
                T t = new T(en);
                t.start();
                list.add(t);
                threadConntLimit--;
                if (threadConntLimit <= 0) {
                    for (int i = 0; i < list.size(); i++) {
                        T ta = list.get(i);
                        if (ta.isAlive()) {
                            try {
                                ta.join();
                            } catch (InterruptedException ex) {
                                java.util.logging.Logger.getLogger(TestHadoop.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        } else {
                            list.remove(i);
                            threadConntLimit++;
                        }
                    }
                }
            }        
            long time = System.currentTimeMillis() - starTime;
            System.out.println("文件数:" + fileMap.size() + "总共用时:" + time);
        }
        
        public static void readFiles(File file) {
            if (file.exists()) {
                if (file.isDirectory()) {
                    for (File f : file.listFiles()) {
                        readFiles(f);
                    }
                } else {
                    fileMap.put(file.getAbsolutePath(), file.getAbsolutePath().replaceAll("D:\\\\", "/").replaceAll("\\\\", "/"));
                }
            }
        }
        
        public static void downloadFile(String src, File target) {
            Configuration conf = new Configuration();        
            conf.set("dfs.socket.timeout", "30000");
            conf.set("dfs.datanode.socket.write.timeout", "30000");        
            conf.setBoolean("fs.hdfs.impl.disable.cache", true);
            conf.set("fs.defaultFS", "hdfs://192.168.254.130:9000");
            try {
                HadoopUtils.downLoadFileFromHDFS(conf, src, target);
            } catch (Exception ex) {
                java.util.logging.Logger.getLogger(TestHadoop.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        public static void writeFile(File file, String target) {
            Configuration conf = new Configuration();
            long i = file.length() / 1024 / 1024;
            conf.set("dfs.socket.timeout", "30000");
            conf.set("dfs.datanode.socket.write.timeout", "30000");
            //conf.set("dfs.blocksize", ((i + 1) * 1024 * 1024) + "");
            conf.setBoolean("fs.hdfs.impl.disable.cache", true);
            conf.set("fs.defaultFS", "hdfs://192.168.254.130:9000");
            try {
                HadoopUtils.uploadFileToHDFS(conf, file, "/test" + target);
            } catch (Exception ex) {
                java.util.logging.Logger.getLogger(TestHadoop.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        class T extends Thread {
            
            private Entry<String, String> en;
            
            public T(Entry<String, String> entry) {
                this.en = entry;
            }
            
            public void run() {
                TestHadoop.writeFile(new File(en.getKey()), en.getValue());
            }
        }
        private static HashMap<String, String> fileMap = new HashMap();
    }

    展开全文
  • Java并发】锁

    2012-02-20 14:04:57
    写:修改内容+删除文件)的工具。通常,锁提供了对共享资源的独占访问:对共享资源的任何访问都需要首先获取锁,一次只能有一个线程获取锁。     锁不仅是关于同步和互斥 的,也是关于内存可见 的。为了...

    简介

     

     

            锁是控制多个线程对共享资源访问(读/写,读:读内容;写:修改内容+删除文件)的工具。通常,锁提供了对共享资源的独占访问:对共享资源的任何访问都需要首先获取锁,一次只能有一个线程获取锁。

     

           锁不仅是关于同步和互斥 的,也是关于内存可见 的。为了保证所有线程都能够看到共享的/可变变量的最新值,读取和写入线程必须使用公共的锁进行同步。

     

         针对有读/写两种不同访问方式,能不能做的更智能一些,有没有锁机制能允许对共享资源并发“读”访问,利用 ReadWriteLock 的读锁可以!!。

     

    JDK 1.5 之前,协调共享对象 的访问(coordinate access to shared data )能采取的机制是synchronized volatile 。在1.5 后,通过显式定义同步锁对象(Lock对象)来实现同步,增加了ReentrantLock 。这样,大致可将锁分为implicit lock(内部锁)explicit lock(显示锁)。

     

     

    一些概念

    同步和互斥

    当多个线程对共享资源访问的时候,很有可能会带来线程安全问题,可以通过同步监视器(synchronized同步块or同步方法)。

     

    独占锁,互斥锁

     

    死锁

    两个线程互相等待对方释放同步监视器时就会发生死锁。一旦出现死锁,整个程序既不会发生任何异常,也不会给出任何提示,所有线程处于阻塞状态。

     

    用锁来保护状态

    一个错误观念:只有在写入共享变量时才需要同步。



    构造线程安全类一种常见的锁规则:

    在对象内部封装可变状态,通过对象的内部锁 来同步任何对这些可变状态访问的代码路径,从而保证在并发访问中的安全。


    Synchronized


    同步方法和同步代码块的粒度:

    同步方法可能会带来活跃度与性能的问题,通过缩小synchronized块的范围我们既可以维护线程安全性,还能比较容易地提升并发性。但也不能让synchronized太小:不可以将一个原子操作分解到多个synchronized块中。不过应该尽量从synchronized块中分离耗时的且不影响共享状态的操作(参考并发编程实践p30) 。对于独享地操作本地(基于栈)变量,这些变量不被多线程共享,可以不放在同步块当中。

    重进入(Reentrancy)

    内部锁是可以重进入的,即线程在试图获取它自己占有的锁时,请求会成功。重进入的实现是通过为每个锁关联一个请求计数和一个占有它的线程。

     

     

    何时释放同步监视器的锁定?

     

     

    Lock接口

     

     

    Lock lock = new ..;
    ...
    lock.lock();
    try{
    //需要锁保护的更新对象的状态
    }finally{
    lock.unlock();
    }

     finally千万不能丢!!

     

    Lock接口实现类有:    ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock。

    其中ReentrantLock实现了标准的互斥锁。

     

    ReentrantLock

     

    可重入

    线程可以对它已经加锁的ReentrantLock锁再次加锁。所以一段被锁保护的代码可以调用另一个被相同锁保护的代码。

     

    synchronized ReentrantLock 间选择

    使用 ReentrantLock 时有些要额外注意的地方,比如在 finally 里调用 unlock()

    ReentrantLock 可伸缩性( scalability )更好。--如何理解??

    对于如何选择可以遵循这样的原则:在内部锁不能满足需求时,再考虑使用 ReentrantLock (内部锁能处理哪些问题??)当需要一些高级特性 时, ReentrantLock 才应该被使用:可定时的( timed )、可轮询的( polled )、可中断的( interruptible )锁获取操作,公平队列,非块结构锁( none-block-structured )。

     

    Volatile

    读一个 volatile 变量时,总能返回由某一线程写的最新值。 Volatile 的一个典型应用是:检查状态标记(完成、中断、其他状态)

    访问volatile变量的操作不会加锁,也就不会引起执行线程的阻塞,volatile相对synchronized而言可以说是轻量级的同步机制。

    Volatile 只能保证变量的“可见性 ”,却不能保证“原子性”。(相比较:加锁既能保证可见性也能保证原子性)。

    示例

    // 判断是否睡觉,没有的话继续数数,如果已睡,则停止数数。

    volatile boolean asleep;

    while(!asleep){

       countNum();

    }

    在考虑使用 volatile 时,思考下面问题

    1. 写入变量时是否依赖变量的当前值?或者是否只有一个线程执行写操作?

    如果不依赖或者能确定只有一个线程写则可以考虑

    2. 变量是否要与其他变量一起参与不变约束?

    如果没有则可以考虑。

    3. 访问变量时,是否有其他原因需要加锁?

    如果没有则可以考虑。


    关于CAS和原子变量的信息可参见http://kenwublog.com/the-theory-of-volatile


     

     

     

     

    读-写锁

    读写锁能够保证一个资源能同时被多个读者访问,或者只被一个写者访问。当对容器“读”操作较多,而很少写的时候,使用ReadWriteLock比使用ReentrantLock能获得更高的吞吐量。如为LinkedHashMap提供更高的并发访问。

    ReadWriteLock lock = new ReentrantReadWriteLock();
    Lock w = lock.writeLock();//获得"写锁"实例
    Lock r = lock.readLock()//获得“读锁”实例
    
    //对写操作加锁
    w.lock();
    try{
       //write operation
    }finally{
       w.unlock();
    }
    //对读操作加锁
    r.lock();
    try{
       //read operation
    }finally{
       r.unlock();
    }
     

     

    能够用同一个读写锁保护不同的资源么?

     

    阅读材料

    http://wenku.baidu.com/view/a0104d39580216fc700afd90.html

    http://www.jdon.com/concurrency.html

    【公司源码查看】: UserAccountLockService

    展开全文
  • Java获取zip文件

    千次阅读 2019-11-23 11:04:14
    项目中经常遇到需要导出压缩文件的情况,...文件删除策略,无用文件及时删除,避免磁盘空间的浪费。 保存到内存中,返回时从内存中读取二进制内容 以流的形式传输数据,避免临时文件的生成,完成后关闭流,z...
  • JAVA并发-基础IO

    2016-10-18 14:43:00
    一、java.io包支持。java的IO流有输入、输出两种,每种输入、输出流又可分为字节流、字符流两大类,字节流...1、java.io包下代表与平台无关的文件、目录,能新建、删除、重命名文件和目录,不能访问文件本身 2、方...
  • 获得代码,保存到本地,调用本地编译器编译文件,执行之后返回结果并删除文件。可以更改为接口,集成到web项目里,达到类似菜鸟工具java在线编程的效果,考虑并发的话需要使用多线程
  • Java 编译器生成的一种代码。...操作系统周期性的删除系统中所有可用的Java文件.自动删除那些被程序引用但未被使用的包当一个对象的引用(references)不再存在,被这些对象占用的内存会被自动的回收。JVM检查...
  • 大家都知道当插入大批量数据MySQL的时候,MySQL使用...这样就需要去写文件,以及文件删除等维护。某些情况下,比如数据源并发的话,还会出现写文件并发问题,很难处理。那么有没有什么办法,可以达到同样的效率,...
  • 文章目录1. 数据结构2. 算法排序动态规划DFS深度优先搜索BFS广度优先搜索双...递归练习1,从键盘接收一个文件的路径,统计该文件的大小 递归练习2 从键盘接收一个文件夹路径,删除该文件夹 递归练习3 从键盘接收两个...
  • 大家都知道当插入大批量数据MySQL的时候, MySQL使用load data local infile 从文件中导入数据比insert语句要快,...某些情况下,比如数据源并发的话,还会出现写文件并发问题,很难处理。 那么有没有什么办法,可以
  • 大家都知道当插入大批量数据MySQL的时候,MySQL使用...这样就需要去写文件,以及文件删除等维护。某些情况下,比如数据源并发的话,还会出现写文件并发问题,很难处理。那么有没有什么办法,可以达到同样的效率,...
  • 每当将新文件添加到目录时,将挑选该文件的内容并在kafka上发布,然后删除文件.这在我发出单个请求时有效,但是一旦我将代码从jMeter请求5或10个用户请求,内容就会在kafka上成功发布,但代码无法删除文件.我收到一个...
  • 这样就需要去写文件,以及文件删除等维护。某些情况下,比如数据源并发的话,还会出现写文件并发问题,很难处理。那么有没有什么办法,可以达到同样的效率,直接从内存(IO流中)中导入数据,而不需要写...
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
  • 2、如果传输过程中服务器端发现客户端断开,服务器端应删除文件,并在屏幕 上提示,如“ IP:1.2.3.4 发来 abcd.txt 文件过程中失去连接。”。如果客户端发 现服务器端不工作,客户端应有提示“服务器
  • JAVA_API1.6文档(中文)

    万次下载 热门讨论 2010-04-12 13:31:34
    java.util.concurrent 在并发编程中很常用的实用工具类。 java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类...
  • java源码包2

    千次下载 热门讨论 2013-04-20 11:28:17
     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
  • java源码包3

    千次下载 热门讨论 2013-04-20 11:30:13
     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
  • 最近开发一个需求是需要获取一个文件,然后将文件下载下来,并发送到制定邮箱,发送之后要对下载的文件进行删除;但是开始一直删除不成功文件;后来才发现原因在于一个流没关闭导致的; public static void ...
  • java 定时执行任务

    2014-01-23 09:20:22
    1.使用java并发库编写定时程序。 如定时上传文件,定时删除日志,定时执行sql 等 下面的程序在每天的23:20:30 后,执行一次具体任务import java.math.BigDecimal;import java.math.MathContext;import java.math....

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 132
精华内容 52
关键字:

java并发删除文件

java 订阅