JUC学习笔记

目录

目录

1.进程和线程

2.wait和sleep区别(4点)

2.1类的不同

2.2关于锁的释放

3.范围不同

4.捕获异常

Lock锁

synchronized和lock的区别

传统生产者消费真问题(synchronized wait  notify)

JUC版的生产者消费者问题

老版升级

 有序线程(配对)

 八锁现象

集合类不安全-CopyOnWriteArrayList

CopyOnWriteArraset

ConcurrentHashMap

Callable

常用的辅助类

 读写锁-ReadWriteLock

阻塞队列-BlockingQueue

同步队列-SynchronousQueue



JUC主要是java8下的三个包

提取首字母

 jdk1.8文档下载链接:https://pan.baidu.com/s/1VW8D9eBXcuTpVnwLv5PJYQ?pwd=afw8 
提取码:afw8

1.进程和线程

进程:一个独立功能的程序

线程:一个进程包含若干个线程

java默认有两个线程:main gc

java是开不了线程的,调用底层的c++调用的方法

并发编程:并发,并行

并发:多线程操作同一个资源,单核cpu,通过快速交换进行使用

并行:多个人一起行走,多核cpu,多个线程同时执行

查看cpu资源System.out.println(Runtime.getRuntime().availableProcessors());

线程的状态 Thread.state

2.wait和sleep区别(4点)

2.1类的不同

wait-->object sleep-->Thread

2.2关于锁的释放

wait会释放锁,sleep不会释放锁

3.范围不同

wait:必须在同步代码块使用

sleep:可以用在任何地方

4.捕获异常

wait:不需要捕获异常,需要唤醒

sleep:需要捕获异常,不需要唤醒

Lock锁

传统的线程synchronized

//线程就是一个单独的资源类
public class ThreadTest {
    public static void main(String[] args) {
//        com.qing.demo01.MyTest myTest = new com.qing.demo01.MyTest();
//        new Thread(myTest).start();
//        获取cpu参数
//        cpu密集型,IO密集型
//        System.out.println(Runtime.getRuntime().availableProcessors());
//    对于单接口的函数式编程,尽量使用lambda表达式
        Ticket ticket = new Ticket();
        new Thread(()->{
            for (int i = 0; i < 60; i++) {
                ticket.sell();
            }
        },"线程1").start();
        new Thread(()->{
            for (int i = 0; i < 60; i++) {
                ticket.sell();
            }
        },"线程2").start();
        new Thread(()->{
            for (int i = 0; i < 60; i++) {
                ticket.sell();
            }
        },"线程3").start();
    }
}
//oop编程降低耦合度,尽量少继承
class Ticket{
    int num=50;
    public synchronized void sell(){
        if(num>0){
            System.out.println(Thread.currentThread().getName()+"售卖第"+num--+"张票");
        }else {
            System.out.println("卖完了");
        }

    }

}

步骤:加锁 ->写业务->解锁

Lock lock=new ReentrantLock();底层源码

公平锁:十分公平可以先到先得

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

public class ThreadTest {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sell();
            }
        }, "线程1").start();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sell();
            }
        }, "线程2").start();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sell();
            }
        }, "线程3").start();
    }
}

//oop编程降低耦合度,尽量少继承
class Ticket {
    int num = 50;
    //    锁头
    Lock lock = new ReentrantLock();

    public void sell() {
//        加锁
        lock.lock();
        try {
//            业务代码
            if (num > 0) {
                System.out.println(Thread.currentThread().getName() + "售卖第" + num-- + "张票");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
//        解锁
        lock.unlock();

    }

}

实现结果一样

synchronized和lock的区别

1.synchronized是指关键字,lock是一个java类

2.synchronzized无法判断锁的状态,lock可以判断是否取到锁

3,synchronzized会自动释放锁,如果不释放锁会造成死锁

4.synchronized 如果线程阻塞的话,就会一直等待,而lock锁就不会一直等

5.synchronized可重入锁,不可以中断,非公平,lock可重入锁有,可以判断,非公平(可自己设置)

6.synchronized适合少量的同步代码块,Lock适合大量同步代码块

传统生产者消费真问题(synchronized wait  notify)

public class A {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.incrpc();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrpc();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
    }


}

//等待 业务 通知
class Data {
    private int nums = 0;

    //增加产品
    public synchronized void incrpc() throws InterruptedException {
        if (nums != 0) {
            this.wait();
        }
        nums++;
        System.out.println(Thread.currentThread().getName() + "生产了产品" + nums);
        this.notifyAll();
    }

    //减少产品
    public synchronized void decrpc() throws InterruptedException {
        if (nums == 0) {
            this.wait();
        }
        System.out.println(Thread.currentThread().getName() + "消费了" + nums);
        nums--;

        this.notifyAll();
    }
}

结果:

注意:(虚假唤醒 if)这是只有两个线程,如果多个线程则会不稳定,

多了c,d两个线程

则会导致:产生错误

 产生错误的原因:

把if换成while

结果正常 

JUC版的生产者消费者问题

老版升级

相交于Synchronized中线程交互wait和notify的问题,Lock中出现了相同的await(等待)signal (唤醒)。 

public class B {
    public static void main(String[] args) {
        Data2 data = new Data2();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.incrpc();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.decrpc();
            }
        }, "B").start();
        new Thread(() -> {
            data.incrpc();
        }, "C").start();
        new Thread(() -> {
                    data.decrpc();
        }, "D").start();
    }


}

//等待 业务 通知
class Data2 {
    private int nums = 0;
    //        创建锁,
    Lock lock = new ReentrantLock();

    //        创建监视器
    Condition condition = lock.newCondition();

    //        condition.await(); 等待
//        condition.signalAll(); 唤醒
    //增加产品
    public void incrpc() {
        lock.lock();
        try {
            while (nums != 0) {
                condition.await();
            }
            nums++;
            System.out.println(Thread.currentThread().getName() + "生产了产品" + nums);
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //减少产品
    public synchronized void decrpc() {
        lock.lock();
        try {
            while (nums == 0) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName() + "消费了" + nums);
            nums--;
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

 结果:

可以实现

 

 有序线程(配对)

问题。使三个线程按照顺序进行输出

补充:在唤醒的时候会重新进入一次锁,重新调用while进行判断

public class C {
    public static void main(String[] args) {
        JUCPC jucpc = new JUCPC();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                jucpc.P1();
            }

        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                jucpc.P2();
            }

        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                jucpc.P3();
            }

        }, "C").start();

    }
}


class JUCPC {
    int nums = 1;
    Lock lock = new ReentrantLock();
    Condition c1 = lock.newCondition();
    Condition c2 = lock.newCondition();
    Condition c3 = lock.newCondition();

    public void P1() {
        lock.lock();
        try {
            while (nums != 1) {
                c1.await();
            }
            System.out.println(Thread.currentThread().getName() + "---->" + nums);
            nums = 2;
            c2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void P2() {
        lock.lock();
        try {
            while (nums != 2) {
                c2.await();
            }
            System.out.println(Thread.currentThread().getName() + "---->" + nums);
            nums = 3;
            c3.signal();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void P3() {
        lock.lock();
        try {
            while (nums != 3) {
                c3.await();
            }
            System.out.println(Thread.currentThread().getName() + "---->" + nums);
            nums = 1;

            c1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}

结果

 八锁现象

深刻理解锁的机制,关于锁的八个问题

补充:import java.util.concurrent.TimeUnit;包下的

TimeUnit工具类,点进去可以看到里面的方法,可以让线程休眠 

情况1:一个类,两个synchronized的方法,一个对象,两个线程。

多个线程使用同一把锁头-顺序执行

情况2:在情况1中的方法1中加入延迟,TimeUtile观察情况

多个线程使用同一把锁头+线程阻塞-随即执行

public class Lock8 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(() -> {
            phone.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            phone.call();
        }, "B").start();
    }
}

class Phone {
    public synchronized void sendemail() {
        System.out.println("发邮件");
    }

    public synchronized void call() {
        System.out.println("打电话");
    }
}

结果: 程序结果不是顺序执行,synchronized 锁住的对象中的方法,两个方法谁先拿到谁先调用

情况3:多个线程有锁和无锁的-随机执行

是类普通(内未加锁的)方法和加锁方法进行比较(未必先调用,就先执行)

如果对锁中的方法未延时,主要看cpu心情,多数,锁内方法先执行,如果对锁内方法进行延迟,且时间足够长时,类内无锁的方法先执行

public class Lock8 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(() -> {
            phone.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            phone.hello();
        }, "B").start();
    }
}

class Phone {
    public synchronized void sendemail() {
        try {
//            时间必须过大,才可以类中未加载的方法先执行,这里设置了2秒和4秒
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发邮件");
    }

    public synchronized void call() {
        System.out.println("打电话");
    }
    public void hello(){
        System.out.println("绝顶聪明");
    }
}

结果:类内普通方法没有锁,不是同步方法,不受锁的影响

 

情况4:多个线程 多锁头-随机执行

public class Lock8 {
    public static void main(String[] args) {
        Phone p1 = new Phone();
        Phone p2 = new Phone();
        new Thread(() -> {
            p1.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            p2.call();
        }, "B").start();
    }
}

class Phone {
    public synchronized void sendemail() {
        try {
//            时间必须过大,才可以类中未加载的方法先执行,这里设置了2秒和4秒
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"发邮件");
    }

    public synchronized void call() {
        System.out.println(Thread.currentThread().getName()+"打电话");
    }
    public void hello(){
        System.out.println("绝顶聪明");
    }
}

结果:B线程,没有延迟的先调用,同是获取方法

情况5:增加静态方法  多线程使用同一个对象 class锁头 -顺序执行

public class Lock8 {
    public static void main(String[] args) {
        Phone p1 = new Phone();
        new Thread(() -> {
            p1.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            p1.call();
        }, "B").start();
    }
}

class Phone {
    public static synchronized void sendemail() {
        try {

            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"发邮件");
    }

    public static synchronized void call() {
        System.out.println(Thread.currentThread().getName()+"打电话");
    }
    public void hello(){
        System.out.println("绝顶聪明");
    }
}

结论:加入static,synchronized锁的是calss,而不是方法的调用者 -顺序执行

情况6:多线程,多对象

public class Lock8 {
    public static void main(String[] args) {
        Phone p1 = new Phone();
        Phone p2 = new Phone();
        new Thread(() -> {
            p1.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            p2.call();
        }, "B").start();
    }
}

class Phone {
    public static synchronized void sendemail() {
        try {

            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"发邮件");
    }

    public static synchronized void call() {
        System.out.println(Thread.currentThread().getName()+"打电话");
    }
    public void hello(){
        System.out.println("绝顶聪明");
    }
}

结果:A线程调用在前面,加入static之后synchronized锁的就是类,谁先调用谁先执行

情况7:多线程 单对象-随机执行

举例:一个静态的同步方法,一个普通的同步方法,一个对象

public class Lock8 {
    public static void main(String[] args) {
        Phone p1 = new Phone();
        new Thread(() -> {
            p1.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            p1.call();
        }, "B").start();
    }
}

class Phone {
    public static synchronized void sendemail() {
        try {

            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"发邮件");
    }

    public  synchronized void call() {
        System.out.println(Thread.currentThread().getName()+"打电话");
    }
    public void hello(){
        System.out.println("绝顶聪明");
    }
}

结果:打电话优先

情况8:多线程,多个对象-随机执行

public class Lock8 {
    public static void main(String[] args) {
        Phone p1 = new Phone();
        Phone p2 = new Phone();
        new Thread(() -> {
            p1.sendemail();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            p2.call();
        }, "B").start();
    }
}

class Phone {
    public static synchronized void sendemail() {
        try {

            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"发邮件");
    }

    public  synchronized void call() {
        System.out.println(Thread.currentThread().getName()+"打电话");
    }
    public void hello(){
        System.out.println("绝顶聪明");
    }
}

结果:打电话优先

总结:

synchronized锁的一个是具体的对象,多线程调用方法内的,按照顺序,先到先得

static synchronized 锁的是具体的一个类,创建多个对象是时候用的是类模板里面的锁,相当于一个锁。在相同的锁内,按照执行顺序执行。不同锁内按照,执行时间。

集合类不安全-CopyOnWriteArrayList

List不安全

举例:创建以ArrayList用10个线程进行跑

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

    }
}

结果:报错,并发下list是不安全的

java.util.ConcurrentModificationException 并发修改异常

修改:

方式1:把ArrayList修改成Vectory、

方式2:Collection.synchronizedList(new ArrayList<>())

把ArrayList改成安全的List

//        把不安全的线程变得安全
List<String> arr = Collections.synchronizedList(new ArrayList<>());

 方式三:在java.util.concurrent.CopyOnWriteArrayList;包下有有CopyOnWriteArrayList

但是CopyOnWriteArrayList读写分离,底层的set和add方法底层都复制了一个新的容器。和synchronized的区别在于,对于新增的数据会进行上锁,然后复制原来的数据再进行修改,修改完之后在进行对原来的数据进行覆盖。但占用内存

补充:CopyOnWriteArrayList和Vectory区别:

Vectory底层试用seychronized进行绑定的,而CopyOnWriteLsit底层是又lock锁实现的,synchronized比lock效率低

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

    }
}

CopyOnWriteArraset

Set<String> objects = new HashSet<>();在多线程也是不安全的,但它和ArrayList大致一样

创建方法也是 

创建方法:

        //不安全
        Set<String> set1 = new HashSet<>();
        //安全效率慢
        Set<String> set2 = Collections.synchronizedSet(new HashSet<>());
        //juc下的创建
        CopyOnWriteArraySet<String> set3 = new CopyOnWriteArraySet<>();

ConcurrentHashMap

创建方法:

        HashMap<String,String> hashMap1 = new HashMap<String,String>();//不安全
        Map<String, String> hashMap2 = Collections.synchronizedMap(new HashMap<String, String>());//安全效率低
        Map hashMap3 = new ConcurrentHashMap();//juc下创建anquanMap

Callable

特点:有返回值,可以抛出异常,支持泛型,重写call方法

new Threa()无法直接调用Callable,但是runable下的实现类FutureTask可以调用

代码测试:

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        Thread无法直接调用Callable的实现类,
//        但是它的子类FutureTask可以调用
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);
        new Thread(futureTask, "A").start();
        // 只执行一次       结果会被缓存,效率高
        new Thread(futureTask, "B").start();
//        get方法可能会阻塞,所以放到最后执行
        Object o = futureTask.get();
        System.out.println(String.valueOf(o));

    }

}

//有返回值,随着泛型的变化而变化
class MyThread implements Callable<String> {

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

常用的辅助类

CountDownLatch:

主要为两个方法:1.countDown()数量减1 2.awite等待计数器归零向下执行

countSownLatch里面的为线程数,必须等待线程数完全执行完之后才可以执行await后面的方法

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(6);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName());
                cdl.countDown();
            },String.valueOf(i)).start();
        }
        System.out.println("close Door");
        cdl.await();
        System.out.println("open");
    }
}

截图:

CyclicBarrier:

官方:允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。

加法计数器:

public class CyclicBarrieDemo {
//    累加器,必须执行到才可以执行
public static void main(String[] args)
{
//    第二个参数传的是Runnable接口
//    必须执行m个线程之后才可以调用预定的线程方法
    CyclicBarrier cyclicBarrier = new CyclicBarrier(4,()->{
        System.out.println("执行预定的线程");
    });
    for (int i = 0; i < 4; i++) {
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName());
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
}

Semaphore:

一个计数的信号量,在概念上,信号量维持一组许可证。

主要两个方法 acquire()得到   release()释放

举例:4个信号量,如果满了就释放,在循环冲重新获取,比如停车位,只有别的车走了,后面的车才可以进来

public class SemaphoreTest {
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(4);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"获取锁");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName()+"释放锁");
                }
            },String.valueOf(i)).start();

        }
    }
}

结果:总共获取了6次,每次最多获取不超过4

 读写锁-ReadWriteLock

主要方法:

Lock lock=(Lock) new ReentrantReadWriteLock();

//写锁lock.writeLock().lock(); lock.writeLock().unlock();

//读锁 lock.readLock().lock(); lock.readLock().lock();

public class ReadWriteLock {
    public static void main(String[] args) {
        MyLock myLock = new MyLock();
        MyLock1 myLock1 = new MyLock1();
//        写入
        for (int i = 0; i < 5; i++) {
            int f1 = i;
            int f2 = i;
            new Thread(() -> {
//                myLock.put(String.valueOf(f1), f2);
                myLock1.put(String.valueOf(f1), f2);

            }).start();
        }
//        读取
        for (int i = 0; i < 5; i++) {
            int f1 = i;
            int f2 = i;
            new Thread(() -> {
//                myLock.pop(String.valueOf(f1));
                myLock1.pop(String.valueOf(f1));
            }).start();
        }
    }
}

class MyLock {
    private volatile Map<String, Object> map = new HashMap<>();

    public void put(String key, Object value) {
        System.out.println(Thread.currentThread().getName() + "写入" + key);
        map.put(key, value);
        System.out.println(Thread.currentThread().getName() + "写入完成");

    }

    public void pop(String key) {
        System.out.println(Thread.currentThread().getName() + "写入" + key);
        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName() + "读取完成");
    }
}

//加锁的
class MyLock1 {
    private volatile Map<String, Object> map = new HashMap<>();
    //    Lock lock=(Lock) new ReentrantReadWriteLock();
//    读写锁
//    写的时候只希望一个线程可以写
    ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void put(String key, Object value) {
//        读锁
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "写入" + key);
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "写入完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            解锁
            lock.writeLock().unlock();
        }
    }

    //    读的时候希望所有线程都可以读
    public void pop(String key) {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "写入" + key);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName() + "读取完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
    }
}

 结果:

阻塞队列-BlockingQueue

ArrayBllockingQueue 有容量

add:添加 添加成功返回true,超过抛异常

remove:按照进队列的顺序进行移除,并返回,取多了抛异常

offer():和add一样超出返回false

poll():和remove一样,超出返回false

element():返回队首的元素,没有抛出异常

peek():返回队首元素,不抛出异常

put();放进去,如果超出一直等待

take():取出,如果没有一直等待

offer("放进去元素","多少","单位"):添加元素,等待超过退出

poll("放进去元素","多少","单位"):去除元素,等待超过退出

    public static void main(String[] args) {
//        创建一个数组类型的消息队列 
        ArrayBlockingQueue<String> bq = new ArrayBlockingQueue<>(3);//队列的大小
        System.out.println(bq.add("a"));
        System.out.println(bq.add("b"));
        System.out.println(bq.add("c"));
        System.out.println(bq.add("d"));//超多大小会报错
    }
}

 结果:

同步队列-SynchronousQueue

没有容量,不存储元素,put一个元素,必须先取出来,否则不能放进去

不需要加锁,源码里面有锁

put:放入元素

take:取出元素
 

public class SynchronousQueueTest {
    public static void main(String[] args) {
//        没有容量
        SynchronousQueue<String> sq = new SynchronousQueue();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"放入1");
                sq.put("1");
                System.out.println(Thread.currentThread().getName()+"放入2");
                sq.put("2");
                System.out.println(Thread.currentThread().getName()+"放入3");
                sq.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();
        new Thread(()->{

            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出"+sq.take());
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出"+sq.take());
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出"+sq.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

结果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值