Java中應用壅塞隊列掌握線程集實例。本站提示廣大學習愛好者:(Java中應用壅塞隊列掌握線程集實例)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中應用壅塞隊列掌握線程集實例正文
隊列以一種先輩先出的方法治理數據。假如你試圖向一個曾經滿了的壅塞隊列中添加一個元素,或是從一個空的壅塞隊列中移除一個元素,將招致線程壅塞。在多線程停止協作時,壅塞隊列是很有效的對象。任務者線程可以按期的把中央成果存到壅塞隊列中。而其他任務者線程把中央成果掏出並在未來修正它們。隊列會主動均衡負載。假如第一個線程集運轉的比第二個慢,則第二個線程集在期待成果時就會壅塞。假如第一個線程集運轉的快,那末它將期待第二個線程集遇上來。
上面的法式展現了若何應用壅塞隊列來掌握線程集。法式在一個目次及它的一切子目次下搜刮一切文件,打印出包括指定症結字的文件列表。
java.util.concurrent包供給了壅塞隊列的4個變種:LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue和DelayQueue。我們用的是ArrayBlockingQueue。ArrayBlockingQueue在結構時須要給定容量,並可以選擇能否須要公正性。假如公正參數被設置了,期待時光最長的線程會優先獲得處置。平日,公正性會使你在機能上支付價值,只要在切實其實異常須要的時刻再應用它。
臨盆者線程列舉在一切子目次下的一切文件並把它們放到一個壅塞隊列中。這個操作很快,假如隊列沒有設下限的話,很快它就包括了沒有找到的文件。
我們同時還啟動了年夜量的搜刮線程。每一個搜刮線程從隊列中掏出一個文件,翻開它,打印出包括症結字的一切行,然後掏出下一個文件。我們應用了一個小技能來在任務停止後終止線程。為了收回完成旌旗燈號,列舉線程把一個虛擬對象放入隊列。(這相似於外行李保送帶上放一個寫著“最初一個包”的虛擬包。)當搜刮線程取到這個虛擬對象時,就將其放回並終止。
留意,這裡不須要人任何顯示的線程同步。在這個法式中,我們應用隊列數據構造作為一種同步機制。
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
public class BlockingQueueTest
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Enter base directory (e.g. /usr/local/jdk1.6.0/src): ");
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);
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().trim();
if (line.contains(keyword)) System.out.printf("%s:%d %s%n", file.getPath(), lineNumber, line);
}
in.close();
}
private BlockingQueue<File> queue;
private String keyword;
}