zoukankan      html  css  js  c++  java
  • synchronized:内部锁

    synchronized:内部锁

    起源: 并行程序开发涉及多线程、多任务间的协作和数据共享

    一)、内部锁:synchronized

    1).定义在方法上

    public synchronized void method()

    当method方法被调用时,调用线程必须获得当前对象的锁。

    锁对象:当前对象。

    2).同步代码块

    synchronized(Object obj){ }

    锁对象:自定义一个共同使用的锁对象。

    好处:

    1.同步块可以更为精确的控制同步代码范围

    2.小的代码块非常有利于锁的快进快出,假设同步块前后代码段较为耗时,而它

    ​ 们又无需进行同步操作,那么,将这些代码纳入整个同步代码块就会增加锁的等

    ​ 待时间。

    3).静态方法的同步

    public synchronized static method()

    锁对象:Class对象

    4).使用wait()、notify()来创建一个阻塞队列

    构建:

    方法一:当队列有数据时,取出第一个元素,没有数据时,线程进入等待状态,线

    ​ 程被阻塞。

    方法二:将一个对象添加进入队列,并通知等待的方法。

    使用wait()、notify()实现了多线程之间的协作以及数据的共享。

    模拟队列:

    /**
     * 使用synchronize和wait(), notify()实现一个阻塞队列
     * 实现:
     *    获取队列中的元素: 使用pop操作队列,当队列中有元素,则取出第一个元素,若队列为空,线程进入等待状态
     *    使用put()方法添加元素,并唤醒等待的线程
     */
    public class BlockQueue {
        List list = new ArrayList<>();
        public synchronized Object pop() throws InterruptedException {
            //当涉及条件判断时,wait方法要在一个循环中使用,并指出跳出循环的条件
            //原因:若使用if语句,线程被唤醒,直接执行接下的业务逻辑,不再进行list.size() == 0的判断,若之前队列的
            //元素被消费,此时又再次唤醒该线程,队列中无数据,执行业务逻辑出错。
            //将wait()放入while中,唤醒线程后会再次进行条件判断,条件满足则执行业务逻辑。
            if(list.size() == 0) {
                this.wait();
            }
            if(list.size() > 0){
                System.out.println("取值");
                return list.remove(0);
            }else{
                return null;
            }
        }
    
        public synchronized void put(Object obj){
            list.add(obj);
            this.notify();
        }
    }
    
    

    测试:

    public class ThreadPoolTest {
        public static void main(String[] args) {
            BlockQueue queue = new BlockQueue();
            //两个线程,一个线程获取队列的数据,如果队列有数据则获取数据,如果没有则等待
            /**
             *  使用线程池来创建线程对象
             */
            ExecutorService executor = Executors.newFixedThreadPool(10);
            //线程一,取数据
            executor.execute(new Runnable(){
                @Override
                public void run(){
                    while(true) {
                        //获取队列的数据
                        try {
                            queue.pop();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            executor.execute(new PopThread(queue));
            //线程二,放数据
            executor.execute( new Runnable(){
                @Override
                public void run(){
                    while(true) {
                       String a = "1";
                        queue.put(a);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    
    
    }
    
    金麟岂能忍一世平凡 飞上了青天 天下还依然
  • 相关阅读:
    Mythological VI
    新访问计划
    数学小记
    【Learning】带花树——一般图最大匹配
    朋友
    【bzoj 1414】对称的正方形 单调队列+manacher
    【半集训记录】
    【codeforces 718E】E. Matvey's Birthday
    【codeforces 718 C&D】C. Sasha and Array&D. Andrew and Chemistry
    【bzoj 3233】[Ahoi2013]找硬币 ——搜索
  • 原文地址:https://www.cnblogs.com/Auge/p/11759944.html
Copyright © 2011-2022 走看看