一 : BlockingQueue接口

来源:互联网 发布:手机淘宝卖家如何退款 编辑:程序博客网 时间:2024/06/05 22:32

注 : 该包类的学习始源于ruoran前辈提供的代码。 自己参考一些文章,才得以系统学习。 在此十分感谢ruoran前辈 。 


一 : 概述 


BlockingQueue 通常用于一个线程生产对象 , 而另外一个线程消费这些对象。 也就是常见的生产者消费者模式。


  一个线程将会持续生产新对象并将其插入到队列之中 , 直到队列达到它所能容纳的临界点。 也就是说,它是有一定界限的。 当该阻塞队列到达了其临界点 ,那么负责生产的线程将会在往里边插入新对象时发生阻塞(有些则是报错,依照不同实现类实现的方法来决定) 。 它会一直处在阻塞之中,直到负责消费的线程从队列中拿走一个对象。

负责消费的线程将会一直从该阻塞队列中拿出对象,如果消费线程尝试去从一个空的队列中提取对象的话,这个消费线程将会处于阻塞之中(有些也是报错)。直到一个生产线程把一个对象丢进队列。




二 : 代码实现


/**
 * 并发库中的BlockingQueue是一个比较好玩的类,顾名思义,就是阻塞队列。该类主要提供了两个方法put()和take(),前者将一个对象放到队列中,如果队列已经满了,就等待直到有空闲节点;后者从head取一个对象,如果没有对象,就等待直到有可取的对象。
 * 下面的例子比较简单,一个读线程,用于将要处理的文件对象添加到阻塞队列中,另外四个写线程用于取出文件对象,为了模拟写操作耗时长的特点,特让线程睡眠一段随机长度的时间。另外,该例子也使用到了线程池和原子整型(AtomicInteger),AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchronized,而且性能非常高。由于阻塞队列的put和take操作会阻塞,为了使线程退出,在队列中添加了一个“标识”,算法中也叫“哨兵”,当发现这个哨兵后,写线程就退出。
 */
public class BlockingQuquq
{

static long randomTime()
{
return (long) (Math.random() * 1000);
}

public static void main(String[] args)
{
// 能容纳100个文件
final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
// 线程池
final ExecutorService exec = Executors.newFixedThreadPool(5);
final File root = new File("D:\\dist\\blank");
// 完成标志
final File exitFile = new File("");
// 读个数
final AtomicInteger rc = new AtomicInteger();
// 写个数
final AtomicInteger wc = new AtomicInteger();
// 读线程
Runnable read = new Runnable()
{
public void run()
{
scanFile(root);
scanFile(exitFile);
}

public void scanFile(File file)
{
if (file.isDirectory())
{
File[] files = file.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
return pathname.isDirectory() || pathname.getPath().endsWith(".log");
}
});

for (File one : files)
{
scanFile(one);
}
}
else
{
try
{
int index = rc.incrementAndGet();
System.out.println("Read0: " + index + " " + file.getPath());
queue.put(file);
}
catch (InterruptedException e)
{
}
}
}
};
exec.submit(read);
// 四个写线程
for (int index = 0; index < 4; index++)
{
// write thread
final int num = index;
Runnable write = new Runnable()
{
String threadName = "Write" + num;

public void run()
{
while (true)
{
try
{
Thread.sleep(randomTime());
int index = wc.incrementAndGet();
File file = queue.take();
// 队列已经无对象
if (file == exitFile)
{
// 再次添加"标志",以让其他线程正常退出
queue.put(exitFile);
break;
}
System.out.println(threadName + ": " + index + " " + file.getPath());
}
catch (InterruptedException e)
{
}
}
}

};
exec.submit(write);
}
exec.shutdown();
}

}

1 0
原创粉丝点击