JUC

java.util.concurrent

并发锁:

 

 Lock接口

有三个实现类:ReentrantLock(可重入锁,常用),ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock

方法:lock()获得锁  unlock() 释放锁

 

  

公平锁:十分公平,可以先来后到

非公平锁:十分不公平:可以插队(默认)synchronized

 

使用lock 锁的三步曲:

1.先创建一个lock锁实例   Lock l = new ReentrantLock();

2.获得锁  l.lock();

3.释放锁  l.unlock();写在finally里面

 消费者与生产者模式:(判断等待条件,业务,通知)

1.通过Synchonized关键字来实现生产者消费者模式(代码里面用到了if判断语句,当有多对生产者消费者线程的时候,这种容易产生虚假唤醒)所以要用到while

package JUC.ProducerAndConsumer;

public class First {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(() -> {for (int i = 0; i < 10; i++)ticket.produce();}, "A").start();
        new Thread(() -> {for (int i = 0; i < 10; i++)ticket.consume();}, "B").start();
    }
}
//生产者消费者模式
// 判断等待 业务 唤醒
class Ticket {
    private int number = 0;

    // 如果数量为0 的时候则生产
    // 数量为1的时候则唤醒另外一个线程执行
    public synchronized void produce() {
        if (number != 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        this.notifyAll();

    }

    public synchronized void consume() {
        // 当数量为0的时候则等待
        if (number == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        number--;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        this.notifyAll();

    }
}

对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}

2.使用JUC实现生产者消费者模式:(await(),signal())

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

Condition 实例实质上被绑定到一个锁定上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

步骤:

1.实例化一把锁 Lock lock = new ReentrantLock();
2.为特定 Lock 实例获得 Condition 实例 Condition condition = lock.newCondition();
3.上锁 lock.lock();
4.写业务代码(判断等待条件,等待,业务,释放锁
5.释放锁 lock.unlock();

package JUC.ProducerAndConsumer;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.*;

public class JUCProducerAndConsumer {

    public static void main(String[] args) {
        Ticket1 ticket = new Ticket1();
        new Thread(()-> {for(int i = 0;i<10;i++) ticket.produce();},"A").start();
        new Thread(()->{for(int i = 0;i<10;i++) ticket.consume();},"B").start();
        new Thread(()-> {for(int i = 0;i<10;i++) ticket.produce();},"C").start();
        new Thread(()-> {for(int i = 0;i<10;i++) ticket.consume();},"D").start();

    }

}

class Ticket1{
    private int number = 0;
    
    //先创建一个锁实例
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    //当数量不为0的时候要等待
    public void produce() {        
        lock.lock();
        try {
            //业务代码
            while(number!=0) {
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition.signalAll();
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放锁
            lock.unlock();
        }
        
    }
    public void consume() {
        lock.lock();
        try {            
            while(number == 0) {
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition.signalAll();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
                
    }
}

3.使用Condition实现精准唤醒通知:

package JUC.ProducerAndConsumer;

import java.util.concurrent.locks.*;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionAccurateNotify {

    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{for(int i = 0;i<10;i++) data.printA();},String.valueOf(1)).start();
        new Thread(()->{for(int i = 0;i<10;i++) data.printB();},String.valueOf(2)).start();
        new Thread(()->{for(int i = 0;i<10;i++) data.printC();},String.valueOf(3)).start();
    }
}
class Data{
    private int number = 2;
    Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();
    
    public void printA() {
        lock.lock();
        try {
            while(number!=1) {
                condition1.await();
            }        
            System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
            number = 2;
            condition2.signal();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        
    }
    public void printB() {
        lock.lock();
        try {
            while(number!=2) {
                condition2.await();
            }
            number = 3;
            System.out.println(Thread.currentThread().getName()+"=>BBBBB");
            condition3.signal();
        }catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    
    public void printC() {
        lock.lock();
        try {
            while(number!=3) {
                condition3.await();
            }
            number = 1;
            System.out.println(Thread.currentThread().getName()+"=>CCCCCCC");
            condition1.signal();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }    
}

 

锁的八大问题:

1.只有一个资源对象 phone,   synchonized,锁的对象是方法的调用者。两个方法用的是同一把锁,谁先拿到就先调用谁。

//会先输出  Send Message!  即使msg()方法里面调用了sleep()方法,但是sleep()方法是抱着锁睡觉的。如果调用wait()方法,那么就会先输出call....

package JUC.ProducerAndConsumer;

import java.util.concurrent.TimeUnit;

public class EightQuestions {

    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(()->{phone.msg();}).start();
        try {
            TimeUnit.SECONDS.sleep(1);//这里的sleep其实是main线程在这里睡眠
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }        
        new Thread(()->{phone.call();}).start();
    }        
}

class Phone{    
    public synchronized void msg() {    
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        System.out.println("Send Message!");
        
    }    
    public synchronized void call() {
        System.out.println("Call...");
    }
}

2.如果增加一个普通方法:(先打印Hello, 在打印Send Message!)

分析:

首先,phone1对象拿到锁先执行了msg()方法,但执行msg()的时候睡眠了2秒而main程序只会睡眠1s.main睡完以后就会接着执行调用sayHello()方法,然后msg()再醒来执行,所以是先打印Hello,再打印Send Message!

TimeUnit.SECONDS.sleep(1);
package JUC.ProducerAndConsumer;

import java.util.concurrent.TimeUnit;

public class EightQuestions {

    public static void main(String[] args) {
        Phone phone1 = new Phone();
        
        new Thread(()->{phone1.msg();},"A").start();
        try {
            System.out.println(Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName());
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }        
        new Thread(()->{phone1.sayHello();},"B") .start();
//        new Thread(()->{phone1.call();},"B").start();
    }        
}

class Phone{    
    public synchronized void msg() {
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("Send Message!");
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }    
        
        
        
    }    
    public synchronized void call() {
        System.out.println("Call...");
    }
    
    
    public void sayHello() {
        System.out.println("Say Hello...");
    }
}

3.创建两个资源对象(先打印Call!再打印Send msg!

分析:此时有两个资源对象,phone1和phone2,那么synchonized锁的就是不同的对象

在调用sendMsg()的时候,phone1资源睡了3s,然后主线程睡眠了1S,那么主线程就会先醒来,然后接着就有phone2资源开始调用call()方法,所以先打印先打印Call!再打印Send msg!

package JUC.ProducerAndConsumer;

import java.util.concurrent.TimeUnit;

public class StaticMethod {

    public static void main(String[] args) {
        Mobile phone1 = new Mobile();
        Mobile phone2 = new Mobile();
        
        new Thread(()->{phone1.sendMsg();}).start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        new Thread(()->{phone2.call();}).start();            
    }
}

class Mobile{
    public synchronized void sendMsg() {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("Send Msg!");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
    }    
    public synchronized void call() {
        System.out.println("Call!");
    }
}

4.增加一个静态方法,那么锁的是类模板(而类模板永远只有一份)

先打印Send msg!再打印Call!

package JUC.ProducerAndConsumer;

import java.util.concurrent.TimeUnit;

public class StaticMethod {

    public static void main(String[] args) {
        Mobile phone1 = new Mobile();
        Mobile phone2 = new Mobile();
        
        new Thread(()->{phone1.sendMsg();}).start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        new Thread(()->{phone2.call();}).start();            
    }
}

class Mobile{
    public static synchronized void sendMsg() {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("Send Msg!");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
    }    
    public static synchronized void call() {
        System.out.println("Call!");
    }
}

5.一个静态同步方法,一个普通同步的方法

先打印Call!再打印Send Msg!

分析:调用sendMsg()会锁类模板,而调用call()方法会锁对象,锁的对象不一样,所以不会干扰。

package JUC.ProducerAndConsumer;

import java.util.concurrent.TimeUnit;

public class StaticMethod {

    public static void main(String[] args) {
        Mobile phone1 = new Mobile();
        
        new Thread(()->{phone1.sendMsg();}).start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        new Thread(()->{phone1.call();}).start();
            

    }

}

class Mobile{
    public static synchronized void sendMsg() {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("Send Msg!");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }    
    public synchronized void call() {
        System.out.println("Call!");
    }
}

 集合类的不安全性

List集合的不安全性解决办法:

  1. 使用Vector
  2. 使用Collections类里面的静态方法Collections.synchronizedList
public class SaveArrayListTest {

    public static void main(String[] args) {
        List<String> list =  Collections.synchronizedList(new ArrayList<>());
        for(int i = 0;i<10;i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

  3.使用JUC里面的类(CopyOnWriteArrayList

package JUC.List;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.*;
public class JUCArrayListTest { public static void main(String[] args) { List<String> list = new CopyOnWriteArrayList<String>(); for(int i=1;i<=10;i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0, 6)); System.out.println(Thread.currentThread().getName()+"==>"+list); },String.valueOf(i)).start(); } } }

Set不安全性:

1.使用Collections类里面的静态方法:synchonizedSet();

public static <T> Set<T> synchronizedSet(Set<T> s)
返回由指定 set 支持的同步(线程安全的)set。为了保证按顺序访问,必须通过返回的 set 完成对底层 set 的所有访问。

package JUC.Set;

import java.util.Collections;
import java.util.concurrent.TimeUnit;
import java.util.*;

public class SaveHashSet {

    public static void main(String[] args) {
        Set<String> set = Collections.synchronizedSet(new HashSet());
        for(int i = 1;i<=10;i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(Thread.currentThread().getName()+"=>"+set);
            },String.valueOf(i)).start();
        }
    }
}

2.JUC实现Set的安全(java.util.concurrent 下的类 CopyOnWriteArraySet

public class JUCSetTest {

    public static void main(String[] args) {
        Set<String> set = new CopyOnWriteArraySet<String>();
        for(int i = 1;i<=10;i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(Thread.currentThread().getName()+"=>"+set);
            },String.valueOf(i)).start();
        }
    }
}

HashMap的不安全性:

当开启多个线程给HashMap里面加元素的时候,会报Exception:  java.util.ConcurrentModificationException

1.使用Collections类里面的静态方法:synchonizedMap

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

public class SaveHashMapTest {

    public static void main(String[] args) {
        Map<Integer,String> map = Collections.synchronizedMap(new HashMap());
        for(int i =1;i<=10;i++) {
            final int temp = i;
            new Thread(()->{
                map.put(temp, UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=>"+map);
            },String.valueOf(i)).start();
        }
    }
}

2.使用JUC实现hashMap的安全性:java.util.concurrent 下的类ConcurrentHashMap

public class JUCHashMapTest {

    public static void main(String[] args) {
        Map<Integer,String> map = new ConcurrentHashMap<>();
        for(int i = 1;i<=10;i++) {
            final int temp = i;
            new Thread(()->{
                map.put(temp, UUID.randomUUID().toString().substring(0, 6));
                System.out.println(Thread.currentThread().getName()+"=>"+map);
            },String.valueOf(i)).start();
        }        
    }
}

 

Callable接口:

public interface Callable<V>
返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。
Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。

1.可以有返回值

2.可以抛出异常

3.call()方法

需要借助于FutureTask 找个类来启动一个线程。

public class FutureTask<V>extends Object implements Runnable,Future <V>,RunnableFuture <V>
可使用 FutureTask 包装 Callable 或 Runnable 对象。因为 FutureTask 实现了 Runnable,

FutureTask(Callable<V> callable)
创建一个 FutureTask,一旦运行就执行给定的 Callable。
FutureTask(Runnable runnable, V result)
创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。

public class TestCallable {

    public static void main(String[] args) {
        MyThread callable = new MyThread();
        FutureTask futureTask = new FutureTask(callable);
        try {
            new Thread(futureTask).start();
            String retureResult = (String)futureTask.get(); //获取callable的返回结果        
            System.out.println(retureResult);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class MyThread implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println("Test Callable");
        return "Success";
    }

}

几个常用的工具类:

java.util.concurrent
CountDownLatch

相当于一个减数器

 

 

 

 只有当所有的子线程都走完了,才会执行接下来的主线程。

只有当所有的子线程都走完了才会执行:System.out.println("Close the door");

public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(4);
        for(int i = 1;i<=4;i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" Get out!");
                countDownLatch.countDown();//减少锁存器的计数,如果计数达到零则释放所有等待的线程。
                System.out.println(String.valueOf("还剩"+countDownLatch.getCount()));//返回当前计数。 
            },String.valueOf(i)).start();
            
        }
        countDownLatch.await();// 当前线程等到锁存器倒计数到零
        System.out.println("Close the door");
    }

}

CyclicBarrier:

java.lang.Object
java.util.concurrent.CyclicBarrier

public CyclicBarrier​(int parties,Runnable barrierAction)
创建一个新的 CyclicBarrier ,当给定数量的参与方(线程)等待它时将跳闸,并且当屏障被触发时执行给定的屏障操作,由进入屏障的最后一个线程执行。

 

相当于加数器。

只有执行完设定的子线程才会执行构造方法里面的线程。

public class CyclicBarrierDemo {

    public static void main(String[] args) {
        //集齐7颗龙珠召唤神龙
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("召唤神龙成功!!");
            System.out.println(Thread.currentThread().getName());//最后执行完的子线程
        });
        
        for(int i = 1;i<=7;i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"正在运行");
                try {
                    cyclicBarrier.await();//等待所有 parties在此障碍上调用 await 
                } catch (InterruptedException | BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();            
        }        
    }
}

软件包 java.util.concurrent
Class Semaphore

  • 计数信号量。 从概念上讲,信号量保持一组许可。 如果有必要,每个acquire()都会阻止,直到有许可证,然后接受。 每个release()添加了许可证,可能会释放阻止收购者。 但是,没有使用实际的许可对象; Semaphore只保留可用数量并相应地采取行动。
public class SemaphoreDemo {

    public static void main(String[] args) {
        //当需要共享资源的时候会用到
        //线程数量:
        Semaphore semaphore = new Semaphore(3);
        for(int i = 1;i<=7;i++) {
            new Thread(()->{                
                try {
                    semaphore.acquire();//先要得到资源
                    System.out.println("这是第"+Thread.currentThread().getName()+"线程");                    
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println("这是第"+Thread.currentThread().getName()+"线程离开");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();//释放资源
                }
            },String.valueOf(i)).start();
        }
    }
}

 

ReentrantReadWriteLock(读写锁)

 

 

 

 

 

 

public class ReentrantReadWriteLockDemo {
   
    public static void main(String[] args) {
        MyThreadLock myThread = new MyThreadLock();
        for(int i = 1;i<=5;i++) {
            final String temp = String.valueOf(i);
            new Thread(()->{myThread.set(temp, temp);},String.valueOf(i)).start();
        }        
        for(int i = 1;i<=5;i++) {
            final String temp = String.valueOf(i);
            new Thread(()->{                
                myThread.get(temp);                
            },String.valueOf(i)).start();
        }
    }
}
class MyThread{
    public volatile Map<String,String> map = new HashMap<String,String>();
    
    public void set(String key,String value) {        
        System.out.println(Thread.currentThread().getName()+"开始写入");
        map.put(key, value);
        System.out.println(Thread.currentThread().getName()+"完成写入");
    }
    
    public void get(String key) {
        System.out.println(Thread.currentThread().getName()+"开始读取");
        map.get(key);
        System.out.println(Thread.currentThread().getName()+"完成读取");
    }
}


class MyThreadLock{
    private volatile Map<String,String> map = new HashMap<String,String>();
    
    ReadWriteLock lock = new ReentrantReadWriteLock();
    
    public void set(String key,String value) {
        lock.writeLock().lock();
        
        try {
            System.out.println(Thread.currentThread().getName()+"开始写入");
            map.put(key, value);
            System.out.println(Thread.currentThread().getName()+"完成写入");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.writeLock().unlock();
        }
        
    }
    
    public void get(String key) {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"开始读取");
            map.get(key);
            System.out.println(Thread.currentThread().getName()+"完成读取");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            lock.readLock().unlock();
        }
    }
}

 阻塞队列 BlockingQueue

 

 

 

 

 

 

 

 

什么情况下我们会使用阻塞队列:多线程并发处理,线程池!

学会使用队列:添加、移除

四组API:
1.抛出异常
2.不会抛出异常
3.阻塞等待
4.超时等待

 

 

add/remove(抛出异常) offer/poll put/take (阻塞等待) offer/poll带参数的方法(超时等待)

如果超过数量,则会抛出异常

java.lang.IllegalStateException: Queue full

java.util.NoSuchElementException

不会抛出异常

数据满了以后offer返回false

poll 没有数值了则返回null

 

put:当数据满了则会一直等待,不会报错,需要try/catch(throws)

put没有返回值

take如果没有值了也会一直等待

boolean offer(E o, long timeout, TimeUnit unit)
将指定的元素插入到此队列的尾部,如果没有可用空间,将等待指定的等待时间(如果有必要)。
E poll(long timeout, TimeUnit unit)
检索并移除此队列的头部,如果此队列中没有任何元素,则等待指定等待的时间(如果有必要)。

add:返回值为true/false

remove:返回移掉的对象

offer:返回值为true/false

poll :返回移掉的对象

put:没有返回值

take:返回移掉的对象

都有一个contains()方法
peek()方法可以查看下一个元素,如果没有值返回null,有值返回对象 peek()方法可以查看下一个元素    

 

 

 

public class AddAndRemove {
  public
static void main(String[] args) { // 设置队列的大小 ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue(3); System.out.println(arrayBlockingQueue.add("1")); System.out.println(arrayBlockingQueue.add("2")); System.out.println(arrayBlockingQueue.add("3")); //System.out.println(arrayBlockingQueue.add("4")); //抛出异常 java.lang.IllegalStateException: Queue full System.out.println(arrayBlockingQueue.remove()); System.out.println(arrayBlockingQueue.remove()); System.out.println(arrayBlockingQueue.remove());
//System.out.println(arrayBlockingQueue.remove()); // 抛出异常 java.util.NoSuchElementException
System.out.println(arrayBlockingQueue.peek()); } }

 

public class OfferAndPoll {

    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue(3);
        System.out.println(arrayBlockingQueue.offer(1));
        System.out.println(arrayBlockingQueue.offer(1));
        System.out.println(arrayBlockingQueue.offer(1));
        //System.out.println(arrayBlockingQueue.offer(1));//  不抛出异常,返回false
        
        for(Integer i:arrayBlockingQueue) {
            System.out.println(i);
        }    
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.peek());
        //System.out.println(arrayBlockingQueue.poll());//  不抛出异常,返回null
} }
public class PutAndTake {

    public static void main(String[] args) throws InterruptedException {
        ArrayBlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue(3);
        arrayBlockingQueue.put(1);
        arrayBlockingQueue.put(2);
        arrayBlockingQueue.put(2);
       //arrayBlockingQueue.put(2); //一直等待  阻塞状态
        System.out.println("peek:"+arrayBlockingQueue.peek());
        System.out.println("contains:"+arrayBlockingQueue.contains(1));
        System.out.println(arrayBlockingQueue.take());
        System.out.println(arrayBlockingQueue.take());
        System.out.println(arrayBlockingQueue.take());
        System.out.println(arrayBlockingQueue.take()); //一直等待  阻塞状态
} }

public class DelayOfferAndPoll {

    public static void main(String[] args) throws InterruptedException {
        ArrayBlockingQueue arrayBlockQueue = new ArrayBlockingQueue(3);
        System.out.println(arrayBlockQueue.offer(1, 1, TimeUnit.SECONDS));
        System.out.println(arrayBlockQueue.offer(1, 1, TimeUnit.SECONDS));
        System.out.println(arrayBlockQueue.offer(1, 1, TimeUnit.SECONDS));
        System.out.println(arrayBlockQueue.offer(1, 1, TimeUnit.SECONDS));//false 阻塞一秒 
        
        System.out.println(arrayBlockQueue.poll(1,TimeUnit.SECONDS));
        System.out.println(arrayBlockQueue.poll(1,TimeUnit.SECONDS));
        System.out.println(arrayBlockQueue.poll(1,TimeUnit.SECONDS));
        System.out.println(arrayBlockQueue.poll(2,TimeUnit.SECONDS));//null  阻塞一秒 
                
    }
}

 

 

SynchonousQueue(put/take)

没有容量,进去一个元素,必须等待取出来之后,才能再往里面放一个元素。

SynchonousQueue和一般的BlockingQueue不一样,存入一个先先取出来才能再存入

public class SynchronousQueueDemo {

    public static void main(String[] args) throws InterruptedException {
        SynchronousQueue<Integer> sq = new SynchronousQueue<Integer>();
        new Thread(() -> {
            try {
                
                System.out.println(Thread.currentThread().getName()+"加入元素1");    
                sq.put(1);
                
                System.out.println(Thread.currentThread().getName()+"加入元素2");    
                sq.put(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T1").start();
        
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName()+"取出元素"+sq.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"取出元素"+sq.take());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        },"T2").start();
    }
}
输出结果:
T1加入元素1
T2取出元素1
T1加入元素2
T2取出元素2
posted @ 2020-11-15 21:50  Joyce502  阅读(91)  评论(0)    收藏  举报