import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; public class BlockingQueueTest {
public static void main(String[] args) {
final BlockingQueue queue = new ArrayBlockingQueue(3); //允许放三个数据的队列 for (int i = 0; i < 2; i++) { //模拟两个线程
new Thread() {
public void run() {
while (true) { //一直是true的话,就一直进来
try {
Thread.sleep((long) (Math.random() * 1000)); //Math.random() 返回小于1的随机数
System.out.println(Thread.currentThread().getName() + "准备放数据!");
queue.put(1); //放数据 当满了三个的时候就放不进去,就阻塞
System.out.println(Thread.currentThread().getName() + "已经放了数据," +
"队列目前有" + queue.size() + "个数据");
} catch (InterruptedException e) {
e.printStackTrace();
} }
} }.start();
} new Thread() {
public void run() {
while (true) { //一直是true的话,就一直进来
try {
//将此处的睡眠时间分别改为100和1000,观察运行结果
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "准备取数据!");
queue.take(); //拿走数据,没有数据取的话就在这里一直堵着
System.out.println(Thread.currentThread().getName() + "已经取走数据," +
"队列目前有" + queue.size() + "个数据");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}

第一题:现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。原始代码如下:

package read;

    public class Test {

        public static void main(String[] args){

            System.out.println("begin:"+(System.currentTimeMillis()/1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
*/
for(int i=0;i<16;i++){ //这行代码不能改动
final String log = ""+(i+1);//这行代码不能改动
{
Test.parseLog(log);
}
}
} //parseLog方法内部的代码不能改动
public static void parseLog(String log){
System.out.println(log+":"+(System.currentTimeMillis()/1000)); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

实现的代码:

package read;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; public class Test { public static void main(String[] args) { //一开始new了四个线程,每个线程都在等待打印,等for循环队列获取数据之后,
//每个线程都将数据打印出来
//parseLog因为打印方法休眠了一秒,所以就实现了1秒打印出四条数据 final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);
for (int i = 0; i < 4; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
String log = queue.take();
parseLog(log);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }).start();
} System.out.println("begin:" + (System.currentTimeMillis() / 1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
*/
for (int i = 0; i < 16; i++) { //这行代码不能改动
final String log = "" + (i + 1);//这行代码不能改动
{
try {
queue.put(log);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Test.parseLog(log);
}
}
} //parseLog方法内部的代码不能改动
public static void parseLog(String log) {
System.out.println(log + ":" + (System.currentTimeMillis() / 1000)); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

第二题:现成程序中的Test类中的代码在不断地产生数据,然后交给TestDo.doSome()方法去处理,就好像生产者在不断地产生数据,消费者在不断消费数据。请将程序改造成有10个线程来消费生成者产生的数据,这些消费者都调用TestDo.doSome()方法去进行处理,故每个消费者都需要一秒才能处理完,程序应保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完后,下一个消费者才能消费数据,下一个消费者是谁都可以,但要保证这些消费者线程拿到的数据是有顺序的。原始代码如下:

package queue;

    public class Test {

        public static void main(String[] args) {

            System.out.println("begin:"+(System.currentTimeMillis()/1000));
for(int i=0;i<10;i++){ //这行不能改动
String input = i+""; //这行不能改动
String output = TestDo.doSome(input);
System.out.println(Thread.currentThread().getName()+ ":" + output);
}
}
} //不能改动此TestDo类
class TestDo {
public static String doSome(String input){ try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String output = input + ":"+ (System.currentTimeMillis() / 1000);
return output;
}
}

实现的代码:

package queue;

import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue; public class Test { public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(1);
final SynchronousQueue<String> queue = new SynchronousQueue<String>();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
String input = queue.take();
String output = TestDo.doSome(input);
System.out.println(Thread.currentThread().getName() + ":" + output);
semaphore.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
} System.out.println("begin:" + (System.currentTimeMillis() / 1000));
for (int i = 0; i < 10; i++) { //这行不能改动
String input = i + ""; //这行不能改动
try {
queue.put(input);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} //不能改动此TestDo类
class TestDo {
public static String doSome(String input) { try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String output = input + ":" + (System.currentTimeMillis() / 1000);
return output;
}
}

ArrayBlockingQueue 阻塞队列和 Semaphore 信号灯的应用的更多相关文章

  1. Condition对象以及ArrayBlockingQueue阻塞队列的实现(使用Condition在队满时让生产者线程等待, 在队空时让消费者线程等待)

    Condition对象 一).Condition的定义 Condition对象:与锁关联,协调多线程间的复杂协作. 获取与锁绑定的Condition对象: Lock lock = new Reentr ...

  2. ArrayBlockingQueue 阻塞队列 生产者 与消费者案例

    package com.originalityTest; import java.net.UnknownHostException; import java.util.ArrayList; impor ...

  3. 10.并发包阻塞队列之ArrayBlockingQueue

    上一节中对并发包中的非阻塞队列ConcurrentLinkedQueue的入队.出队做了一个简要的分析,本文将对并发包中的阻塞队列做一个简要分析. Java并发包中的阻塞队列一共7个,当然他们都是线程 ...

  4. 并发包阻塞队列之ArrayBlockingQueue

    并发包阻塞队列之ArrayBlockingQueue   jdk1.7.0_79  上一节中对并发包中的非阻塞队列ConcurrentLinkedQueue的入队.出队做了一个简要的分析,本文将对并发 ...

  5. BlockingQueue-线程的阻塞队列

    BlockingQueue作为线程容器,可以为线程同步提供有力的保障,其主要用到的方法包括: add(E o); //将指定的元素添加到此队列中(如果立即可行),在成功时返回 true,其他情况则抛出 ...

  6. 并发库应用之十一 & 阻塞队列的应用

    队列包含固定长度的队列和不固定长度的队列,队列的规则就是:先进先出.固定长度的队列往里放数据,如果放满了还要放,阻塞式队列就会等待,直到有数据取出,空出位置后才继续放:非阻塞式队列不能等待就只能报错了 ...

  7. JAVA可阻塞队列-ArrayBlockingQueue

    在前面的的文章,写了一个带有缓冲区的队列,是用JAVA的Lock下的Condition实现的,但是JAVA类中提供了这项功能,就是ArrayBlockingQueue, ArrayBlockingQu ...

  8. Java并发之BlockingQueue 阻塞队列(ArrayBlockingQueue、LinkedBlockingQueue、DelayQueue、PriorityBlockingQueue、SynchronousQueue)

    package com.thread.test.thread; import java.util.Random; import java.util.concurrent.*; /** * Create ...

  9. Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

    1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...

随机推荐

  1. 【转】Spark源码分析之-Storage模块

    原文地址:http://blog.csdn.net/aiuyjerry/article/details/8595991 Storage模块主要负责数据存取,包括MapReduce Shuffle中间结 ...

  2. Chapter 3 Phenomenon——2

    I had enough trouble not falling down when the ground was dry; it might be safer for me to go back t ...

  3. js便签笔记(1)——说说HTMLCollection、NodeList以及NamedNodeMap

    介绍 在js的dom操作中,除了常用的document.html**Element之外,还有三个集合对象,即HTMLCollection.NodeList以及NamedNodeMap.试看以下操作: ...

  4. springboot-8- 日志配置

    1, logback配置 springboot 默认支持logback, 自动加载classpath:logback-spring.xml <!-- logback多文件输出 --> &l ...

  5. Mysql——权限管理

    安装Mysql时会自动安装一个名为mysql的数据库.这个数据库下面存储的是权限表. mysql> show databases; +--------------------+ | Databa ...

  6. C#语法之匿名函数和Lambda表达式

    上一篇博客主要是对委托和事件做了一小结,这篇是在上一篇博客的基础上对匿名函数和Lambda表达式小结.还是接着上一篇说起,在上一篇中也说了委托是一种数据结构,主要是解决让函数作为参数的问题.在使用委托 ...

  7. Java基础-内部类介绍

    java内部类介绍 内部类一共分为4种 成员内部类 静态内部类 方法内部类 匿名内部类 下面我会为大家详细介绍每一个内部类!! 成员内部类 成员内部类就好像是外部类的一个成员属性,也是内部类中最常见的 ...

  8. mysql中的坑

    1,MySQL建表中double类型不能限制数据长度! 2,……

  9. oracle数据库逐步学习总结【基础二】

    原创作品,转载请在文字开头明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10067872.html 接着上一篇,继续总结! 五.oracle表管理 首 ...

  10. WebApiTestHelpPage

    这是个什么鬼,第一次见到的时候,我也不知道就花几天时间看了下它的代码 在网上搜索WebApiTestHelpPage会出来很多相关页面   但是它们都是介绍怎么用的,要么就是怎么添加注释   它是怎么 ...