在多线程环境下,Java提供了一系列线程安全的集合类,称为并发集合。并发集合可以保证在多线程环境下,对集合的操作是线程安全的,不会出现线程安全问题。Java中常见的并发集合包括:ConcurrentHashMap、ConcurrentLinkedQueue、CopyOnWriteArrayList等。
ConcurrentHashMap是一种线程安全的HashMap实现,支持高并发的读写操作。ConcurrentHashMap内部采用分段锁的机制,每个段(Segment)维护着一个HashEntry数组,多个线程可以同时访问不同的段,从而提高了并发性能。示例代码如下:
arduinoCopy codeConcurrentMap<String, String> map = new ConcurrentHashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
String value = map.get("key1");
ConcurrentLinkedQueue是一种线程安全的队列实现,基于链表实现。ConcurrentLinkedQueue内部采用CAS(Compare And Swap)算法实现并发安全,不需要使用锁。示例代码如下:
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("element1");
queue.offer("element2");
String element = queue.poll();
CopyOnWriteArrayList是一种线程安全的List实现,基于数组实现。CopyOnWriteArrayList的写操作会创建一个新的数组,并将原数组的数据复制到新数组中,然后将新数组赋值给内部数组,从而保证写操作不会影响到其他线程的读操作。示例代码如下:
List<String> list = new CopyOnWriteArrayList<>();
list.add("element1");
list.add("element2");
String element = list.get(0);
下面通过一个示例来演示如何使用线程池和并发集合。
假设有一个任务需要读取多个文件中的数据,并统计每个单词出现的次数,最终将结果输出到文件中。假设有100个文件需要处理,每个文件的大小为100MB。我们可以使用线程池和并发集合来实现这个任务。
首先,我们可以使用CachedThreadPool来创建一个可缓存的线程池,因为任务的大小是不确定的,线程池的大小需要根据实际情况动态调整。
ExecutorService executor = Executors.newCachedThreadPool();
然后,我们可以使用ConcurrentHashMap来存储每个单词出现的次数,因为ConcurrentHashMap是线程安全的HashMap实现。
ConcurrentMap<String, Integer> wordCount = new ConcurrentHashMap<>();
接着,我们可以创建一个任务类,用来读取文件中的数据并更新单词出现次数。任务类需要实现Runnable接口,示例代码如下:
class WordCountTask implements Runnable {
private File file;
private ConcurrentMap<String, Integer> wordCount;
public WordCountTask(File file, ConcurrentMap<String, Integer> wordCount) {
this.file = file;
this.wordCount = wordCount;
}
@Override
public void run() {
try (BufferedReader reader = new BufferedReader(new FileReader(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();
}
}
}
最后,我们可以提交任务到线程池中,并等待所有任务执行完成。执行完所有任务后,我们可以将单词出现次数按照字典序排序,并输出到文件中。
File[] files = new File("path/to/files").listFiles();
for (File file : files) {
executor.submit(new WordCountTask(file, wordCount));
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
List<Map.Entry<String, Integer>> list = new ArrayList<>(wordCount.entrySet());
list.sort(Map.Entry.comparingByKey());
try (PrintWriter writer = new PrintWriter(new FileWriter("output.txt"))) {
for (Map.Entry<String, Integer> entry : list) {
writer.println(entry.getKey() + " " + entry.getValue());
}
} catch (IOException e) {
e.printStackTrace();
}
以上就是使用线程池和并发集合实现任务的示例代码。通过使用线程池和并发集合,我们可以提高任务的执行效率和并发性能,同时避免线程安全问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。