import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Scanner; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * * 阻塞队列LinkedBlockingQueue和ArrayBlockingQueue的使用 * */ public class BlockingQueueTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter base directory (e.g. /tmp/work/): "); String directory = in.nextLine(); System.out.print("Enter keyword (e.g. volatile): "); String keyword = in.nextLine(); final int FILE_QUEUE_SIZE = 10;// 阻塞队列大小 final int SEARCH_THREADS = 100;// 关键字搜索线程个数 // BlockingQueue<File> queue = new // ArrayBlockingQueue<File>(FILE_QUEUE_SIZE); BlockingQueue<File> queue = new LinkedBlockingQueue<File>( FILE_QUEUE_SIZE); // 只启动一个线程来搜索目录 FileEnumerationTask enumerator = new FileEnumerationTask(queue, new File(directory)); new Thread(enumerator).start(); // 启动100个线程用来在文件中搜索指定的关键字 for (int i = 1; i <= SEARCH_THREADS; i++) new Thread(new SearchTask(queue, keyword)).start(); } } class FileEnumerationTask implements Runnable { // 哑元文件对象,放在阻塞队列最后,用来标示文件已被遍历完 public static File DUMMY = new File(""); private BlockingQueue<File> queue; private File startingDirectory; public FileEnumerationTask(BlockingQueue<File> queue, File startingDirectory) { this.queue = queue; this.startingDirectory = startingDirectory; } public void run() { try { enumerate(startingDirectory); queue.put(DUMMY);// 执行到这里说明指定的目录下文件已被遍历完 } catch (InterruptedException e) { } } // 将指定目录下的所有文件以File对象的形式放入阻塞队列中 public void enumerate(File directory) throws InterruptedException { File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) enumerate(file); else // 将元素放入队尾,如果队列满,则阻塞 queue.put(file); } } } class SearchTask implements Runnable { private BlockingQueue<File> queue; private String keyword; public SearchTask(BlockingQueue<File> queue, String keyword) { this.queue = queue; this.keyword = keyword; } public void run() { try { boolean done = false; while (!done) { // 取出队首元素,如果队列为空,则阻塞 File file = queue.take(); if (file == FileEnumerationTask.DUMMY) { // 取出来后重新放入,好让其他线程读到它时也很快的结束 queue.put(file); done = true; } else search(file); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { } } public void search(File file) throws IOException { Scanner in = new Scanner(new FileInputStream(file)); int lineNumber = 0; while (in.hasNextLine()) { lineNumber++; String line = in.nextLine(); if (line.contains(keyword)) System.out.printf("%s:%d:%s%n", file.getPath(), lineNumber, line); } in.close(); } }
相关推荐
Java中的`LinkedBlockingQueue`和`ArrayBlockingQueue`都是`java.util.concurrent`包下的线程安全队列,它们都实现了`BlockingQueue`接口,提供了一种高效、线程安全的数据同步方式。这两种队列在很多方面都有相似之...
ArrayBlockingQueue和LinkedBlockingQueue的主要区别在于存储元素的方式,ArrayBlockingQueue使用数组存储元素,而LinkedBlockingQueue使用链表存储元素。因此,ArrayBlockingQueue更适合固定大小的队列,而...
LinkedBlockingQueue和ConcurrentLinkedQueue是Java并发包中两个常用的线程安全队列,它们各有特点,适用于不同的场景。本文将深入探讨两者之间的差异以及如何根据需求选择合适的队列。 首先,LinkedBlockingQueue...
同时,LinkedBlockingQueue也使用Condition实现条件变量,用于队列为空和队列已满的情况下阻塞等待。 四、 LinkedBlockingQueue的优点 LinkedBlockingQueue相比ArrayBlockingQueue,LinkedBlockingQueue的优点是...
2. 使用非空构造器:如果队列必须保持非空状态,可以使用`new LinkedBlockingQueue(1)`这样的构造器。 3. 避免死锁:确保多个`BlockingQueue`的操作顺序一致,防止死锁的发生。 4. 谨慎使用`peek()`:该方法不会...
`ArrayBlockingQueue` 内部使用了两个等待条件变量 `notFull` 和 `notEmpty`,它们都是 `ReentrantLock` 的 `Condition` 对象。当队列满时,`put()` 操作会调用 `notFull.await()` 让当前线程等待,而 `take()` 或 ...
ArrayBlockingQueue使用ReentrantLock和两个Condition来实现线程安全的操作。ReentrantLock是Java并发编程中常用的锁实现,它可以重入锁,允许同一个线程多次获得锁。两个Condition分别是notEmpty和notFull,用于...
下面通过一个具体的例子来说明如何使用 `LinkedBlockingQueue`: ```java import java.util.concurrent.*; public class BlockingQueueTest2 { // 定义一个篮子类 public class Basket { // 初始化篮子的容量...
相比于基于数组的`ArrayBlockingQueue`,`LinkedBlockingQueue`在大多数情况下具有更好的性能,因为插入和删除操作不需要数组的重新分配。 五、公平与非公平策略 `LinkedBlockingQueue`有两种策略:公平(FIFO)和...
《深入理解LinkedBlockingQueue与单向链表结构》 LinkedBlockingQueue是Java并发包`java.util.concurrent`中的一个先进先出(FIFO)队列,它基于链表结构实现,特别适用于高并发场景。该队列的主要特点是其内部数据...
ArrayBlockingQueue内部由一个数组`items`存储元素,使用两个指针`head`和`tail`分别表示队头和队尾。在并发环境下,为了保证线程安全,ArrayBlockingQueue采用了ReentrantLock(可重入锁)来实现同步,并且在某些...
与数组结构的`ArrayBlockingQueue`不同,`LinkedBlockingQueue`使用单向链表实现,这使得插入和删除操作的效率相对较高,因为它们只需要修改相邻节点的引用。链表的头节点`head`不包含有效数据,而尾节点`last`保存...
它们分别基于链表、数组和优先级堆实现,其中 ArrayBlockingQueue 和 LinkedBlockingQueue 使用 ReentrantLock 和 Condition 实现线程安全,PriorityBlockingQueue 则是一个按优先级排序的队列。 在选择并发容器时...
通常,我们会选择实现BlockingQueue的类,如ArrayBlockingQueue、LinkedBlockingQueue或PriorityBlockingQueue,根据实际需求选择合适的实现。 例如,我们可以创建一个配置类,如下所示: ```java @Configuration ...
4. **阻塞队列**:BlockingQueue接口及其实现类如LinkedBlockingQueue和ArrayBlockingQueue,是线程间通信的重要工具。它们允许线程在队列满时等待,空时阻塞,保证了数据的有序处理。 5. **CyclicBarrier和...
`LinkedBlockingQueue`的实现充分利用了Java的`java.util.concurrent`包,提供了线程安全的数据结构和操作。 在`LinkedBlockingQueue`中,元素唯一性是一个重要的概念。这意味着队列中的每个元素都是独一无二的,...
`TestBlockingQueue.java`可能包含如何使用`ArrayBlockingQueue`、`LinkedBlockingQueue`等实现线程间的通信和数据交换的示例。 3. **CompletionService**:`CompletionService`提供了一种获取异步任务结果的机制,...
Java的`BlockingQueue`接口提供了线程安全的数据结构,可以方便地实现这种模式,如`ArrayBlockingQueue`、`LinkedBlockingQueue`等。 再者,反射是Java提供的一种强大功能,允许程序在运行时动态访问和修改类的信息...