首页后端开发JAVAjava线程池和并发集合(三)

java线程池和并发集合(三)

时间2023-04-05 16:42:01发布访客分类JAVA浏览875
导读:并发集合的使用场景非常广泛,可以用来解决多线程并发访问数据时的线程安全问题。在实际应用中,我们通常会使用以下几种并发集合:ConcurrentHashMapConcurrentHashMap 是 Java 中线程安全的哈希表,它是一种高效的...

并发集合的使用场景非常广泛,可以用来解决多线程并发访问数据时的线程安全问题。在实际应用中,我们通常会使用以下几种并发集合:

ConcurrentHashMap

ConcurrentHashMap 是 Java 中线程安全的哈希表,它是一种高效的并发容器,可以支持高并发、高吞吐量的读写操作。与传统的 HashMap 不同,ConcurrentHashMap 采用了分段锁机制,它将哈希表分成若干个段,每个段都有一个独立的锁,多个线程可以同时访问不同的段,从而提高了并发性能。

ConcurrentHashMap 的常用方法如下:

  • put(key, value):向 Map 中添加元素,如果 key 已经存在则更新 value。
  • get(key):根据 key 获取对应的 value。
  • remove(key):根据 key 删除元素。
  • size():获取 Map 中元素的个数。

下面是一个示例代码,演示了如何使用 ConcurrentHashMap 来统计一段文本中单词出现的次数:

ConcurrentMapString, Integer>
     wordCount = new ConcurrentHashMap>
    ();

try (BufferedReader reader = new BufferedReader(new FileReader("path/to/file"))) {
    
    String line;

    while ((line = reader.readLine()) != null) {
    
        String[] words = line.split(" ");

        for (String word : words) {
    
            wordCount.compute(word, (k, v) ->
     v == null ? 1 : v + 1);

        }

    }

}
 catch (IOException e) {
    
    e.printStackTrace();

}
    

CopyOnWriteArrayList

CopyOnWriteArrayList 是一种线程安全的动态数组,它采用了读写分离的策略,每次写操作都会创建一个新的数组副本,并在新副本上进行操作,从而避免了读写冲突。因此,CopyOnWriteArrayList 在读多写少的场景下表现出色,但是在写多读少的场景下性能较差。

CopyOnWriteArrayList 的常用方法如下:

  • add(element):向 List 中添加元素。
  • get(index):根据索引获取元素。
  • remove(index):根据索引删除元素。
  • size():获取 List 中元素的个数。

下面是一个示例代码,演示了如何使用 CopyOnWriteArrayList 来实现一个并发的任务队列:

CopyOnWriteArrayListRunnable>
     taskQueue = new CopyOnWriteArrayList>
    ();
    
Executor executor = Executors.newFixedThreadPool(10);
    

// 添加任务到队列中
taskQueue.add(() ->
     System.out.println("Task 1"));
    
taskQueue.add(() ->
     System.out.println("Task 2"));


// 从队列中获取任务,并提交到线程池中执行
for (Runnable task : taskQueue) {
    
    executor.execute(task);

}
    

BlockingQueue

BlockingQueue 是一种阻塞队列,它可以在队列为空时阻塞消费者线程,直到队列中有新的元素可以消费;同时,在队列已满时,BlockingQueue 也可以阻塞生产者线程,直到队列中有空闲位置可以生产。因此,BlockingQueue 适合于生产者消费者模式的场景,可以帮助我们优雅地解决生产者消费者的线程同步问题。

BlockingQueue 的常用方法如下:

  • put(element):向队列中添加元素,如果队列已满则阻塞。
  • take():从队列中获取元素,如果队列为空则阻塞。
  • offer(element, timeout, unit):向队列中添加元素,在指定的时间内等待空闲位置,如果超时则返回 false。
  • poll(timeout, unit):从队列中获取元素,在指定的时间内等待可用元素,如果超时则返回 null。
  • size():获取队列中元素的个数。

下面是一个示例代码,演示了如何使用 BlockingQueue 来实现一个生产者消费者模式:

BlockingQueueInteger>
     queue = new ArrayBlockingQueue>
    (10);
    

// 生产者线程
new Thread(() ->
 {

    while (true) {

        try {
    
            int value = produce();
    
            queue.put(value);
    
            System.out.println("Produced: " + value);
    
            Thread.sleep(1000);

        }
 catch (InterruptedException e) {
    
            e.printStackTrace();

        }

    }

}
    ).start();
    

// 消费者线程
new Thread(() ->
 {

    while (true) {

        try {
    
            int value = queue.take();
    
            consume(value);
    
            System.out.println("Consumed: " + value);
    
            Thread.sleep(1000);

        }
 catch (InterruptedException e) {
    
            e.printStackTrace();

        }

    }

}
    ).start();
    

上面的示例代码中,生产者线程不断地生产数据,将数据放入 BlockingQueue 中;消费者线程则不断地从 BlockingQueue 中取出数据,并进行消费。由于 BlockingQueue 实现了线程安全的阻塞队列,因此我们可以放心地使用它来解决生产者消费者模式的线程同步问题。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

java

若转载请注明出处: java线程池和并发集合(三)
本文地址: https://pptw.com/jishu/1872.html
HTML5 诞生背后的故事|历史上的今天 java线程池和并发集合(二)

游客 回复需填写必要信息