BlockingQueue

In this chapter you will learn:

  1. How to use Java BlockingQueue with multiple threads
  2. BlockingQueue and Executors
  3. File searching with BlockingQueue

Use BlockingQueue

The java.util.concurrent package has several interfaces and classes that are concurrency-oriented extensions to the Collections Framework.

BlockingDeque is a subinterface of BlockingQueue and java.util.Deque. BlockingDeque supports blocking operations. The LinkedBlockingDeque class implements BlockingDeque.

BlockingQueue is a subinterface of java.util.Queue that supports blocking operations. ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedTransferQueue, PriorityBlockingQueue, and SynchronousQueue classes implements BlockingQueue.

ArrayBlockingQueue supports an optional fairness policy for ordering waiting producer and consumer threads.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/*  j  a  v a  2s . co  m*/
public class Main {
  public static void main(String[] argv) throws Exception {
    int capacity = 10;
    BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(capacity);

    int numWorkers = 2;
    Worker[] workers = new Worker[numWorkers];
    for (int i = 0; i < workers.length; i++) {
      workers[i] = new Worker(queue);
      workers[i].start();
    }

    for (int i = 0; i < 10; i++) {
      queue.put(i);
    }
  }
}

class Worker extends Thread {
  BlockingQueue<Integer> q;

  Worker(BlockingQueue<Integer> q) {
    this.q = q;
  }

  public void run() {
    try {
      while (true) {
        Integer x = q.take();
        if (x == null) {
          break;
        }
        System.out.println(x);
      }
    } catch (InterruptedException e) {
    }
  }
}

The code above generates the following result.

BlockingQueue and Executors

The following code uses Executors.newFixedThreadPool to host two threads. One is for adding elements to the queue and another is to take elements out of the queue.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*from  ja v  a2 s  .c o m*/
public class Main {
  public static void main(String[] args) {
    final BlockingQueue<Character> bq = new ArrayBlockingQueue<Character>(26);
    final ExecutorService executor = Executors.newFixedThreadPool(2);
    Runnable producer;
    producer = new Runnable() {
      public void run() {
        for (char ch = 'A'; ch <= 'F'; ch++) {
          try {
            bq.put(ch);
            System.out.println("putting:"+ch);
          } catch (InterruptedException ie) {
            assert false;
          }
        }
      }
    };
    executor.execute(producer);
    Runnable consumer;
    consumer = new Runnable() {
      public void run() {
        char ch = '\0';
        do {
          try {
            ch = bq.take();
            System.out.println("getting:"+ch);
          } catch (InterruptedException ie) {
          }
        } while (ch != 'F');
        executor.shutdownNow();
      }
    };
    executor.execute(consumer);
  }
}

The code above generates the following result.

File searching with BlockingQueue

The following code shows how to use BlockingQueue to do file searching. It has two threads. One is for getting all files and puts it to a queue and another thread read each file in the queue and does the search.

/*// ja v  a  2  s  .  c  om
   This program is a part of the companion code for Core Java 8th ed.
   (http://horstmann.com/corejava)

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * @version 1.0 2004-08-01
 * @author Cay Horstmann
 */
public class Main
{
   public static void main(String[] args)
   {
      String directory = "c:/";
      String keyword = "Java";

      final int FILE_QUEUE_SIZE = 10;
      final int SEARCH_THREADS = 100;

      BlockingQueue<File> queue = new ArrayBlockingQueue<File>(FILE_QUEUE_SIZE);

      FileEnumerationTask enumerator = new FileEnumerationTask(queue, new File(directory));
      new Thread(enumerator).start();
      for (int i = 1; i <= SEARCH_THREADS; i++)
         new Thread(new SearchTask(queue, keyword)).start();
   }
}

/**
 * This task enumerates all files in a directory and its subdirectories.
 */
class FileEnumerationTask implements Runnable
{
   /**
    * Constructs a FileEnumerationTask.
    * @param queue the blocking queue to which the enumerated files are added
    * @param startingDirectory the directory in which to start the enumeration
    */
   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)
      {
      }
   }

   /**
    * Recursively enumerates all files in a given directory and its subdirectories
    * @param directory the directory in which to start
    */
   public void enumerate(File directory) throws InterruptedException
   {
      File[] files = directory.listFiles();
      for (File file : files)
      {
         if (file.isDirectory()) enumerate(file);
         else queue.put(file);
      }
   }

   public static File DUMMY = new File("");

   private BlockingQueue<File> queue;
   private File startingDirectory;
}

/**
 * This task searches files for a given keyword.
 */
class SearchTask implements Runnable
{
   /**
    * Constructs a SearchTask.
    * @param queue the queue from which to take files
    * @param keyword the keyword to look for
    */
   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)
      {
      }
   }

   /**
    * Searches a file for a given keyword and prints all matching lines.
    * @param file the file to search
    */
   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();
   }

   private BlockingQueue<File> queue;
   private String keyword;
}

Next chapter...

What you will learn in the next chapter:

  1. What is Semaphore
  2. A producer and consumer that use semaphores
Home » Java Tutorial » Thread
Thread introduction
Thread Name
Thread Main
Thread sleep
Thread Creation
Thread join and is alive
Thread priorities
Thread Synchronization
Interthread Communication
Thread Step
Thread suspend, resume, and stop
ThreadGroup
BlockingQueue
Semaphore
ReentrantLock
Executor
ScheduledThreadPoolExecutor