当前位置: 首页 > news >正文

阿里云医疗网站建设什么是网站主题

阿里云医疗网站建设,什么是网站主题,网页设计师培训学院,北京海淀区是几环案例一-线程安全的单例模式(面试)是一种设计模式,设计模式针对写代码时的一些常见场景给出一些经典解决方案单例模式的两种典型实现饿汉模式懒汉模式饿汉的单例模式:比较着急去进行创建实例懒汉的单例模式,是不太着急创建实例,,只是在用的时候,才真正创建这个是类对象,也就是.c…案例一-线程安全的单例模式(面试)是一种设计模式,设计模式针对写代码时的一些常见场景给出一些经典解决方案单例模式的两种典型实现饿汉模式懒汉模式饿汉的单例模式:比较着急去进行创建实例懒汉的单例模式,是不太着急创建实例,,只是在用的时候,才真正创建这个是类对象,也就是.class文件,被JVM加载到内存后,表现出的模样类对象里就有.class文件中的一切信息包括:类名是啥,类里有哪些属性,每个属性叫什么.....有了这些信息才能实现反射1.饿汉模式针对唯一实例的初始化,比较着急,类加载阶段,就会直接创建实例对于getinstance 仅仅是读取了变量的内容, 如果是多个线程只是读同一个变量不修改,此时任然是线程安全的class Singleton{ //饿汉模式 //使用static创建唯一实例,并且立即进行实例化.是这个类的唯一实例 private static Singleton instancenew Singleton(); //防止程序员一不小心创建,把构造方法设为private private Singleton(){} //创建一个方法.拿到唯一实例 public static Singleton getInstance(){ return instance; }}2.懒汉模式1)初始模板这个方法的好处就是在真正使用getInstacne的时候才会真的创建实例这里既包含了读,也包含了修改读和修改是分成两个步骤的,并不是原子性的这样就很可能涉及到线程安全的问题还是根之前的count同样的原理先是读取到cpu上,然后实例化,再存到对应的内存上2)避免线程不安全加锁,不能随便加synchronized这里的读没加锁,写加锁,还是没用.还是没用把读和写放在一起这里的类对象作为锁对象,类对象在一个程序中只有一份,能保证多个线程调用getinstance的时候都是针对同一个对象加锁3)锁竞争问题虽然初始化问题的线程安全搞定了但是如果初始化后,if的条件就不成立了,getinsance就只剩下读操作,就线程安全 了,但是如果代码就这样,无论初始化前后每次进入都会加锁,也就存在大量锁竞争这样速度就变慢了解决方案让初始化之前才进行加锁,初始化之后就不加锁了.就再进行一条条件判定加锁很有可能导致代码出现阻塞,第一个if判定的是否要加锁第二个if判定是否要创建实例3)内存可见性问题如果多个线程都去调用这里的getinsance.就会造成大量的读内存操作很有可能会让编译器把读内存操作优化成读寄存器操作如果这样的话,就算已经实例化第一层就会误认为是null就会导致不该加锁的锁给加了但是不会影响第二层的if-synchroized可以预防内存可见性解决方法:给instance加上volatile保证insance不会被编译器优化4)总结①给正确的位置加锁②双重if判定③volatile内存可见性问题案例二--------阻塞队列阻塞队列符合先进先出规则的队列0.功能1.线程安全2,产生阻塞效果1)如果队列为空,尝试出队列,就会出现堵塞,阻塞到队列不为空为止2)如果队列为满,尝试入队列,就会出现阻塞,阻塞到入列不为满为止基于上述特性,就可以实现生产者-消费者模型阻塞队列可以作为生产者消费者模型中的交易场所生产者消费者模型.是服务器开发的场景常用1.优点优点1 可以让多个服务器程序之间充分的解耦合此时A和B的耦合性比较强开发A代码的时候就得充分了解到B提供的一些接口开发B代码的时候也得充分了解A是如何调用的一旦B发生改动,A也要改动使用生产者消费者模型,就可以降低这里的耦合对于 请求:A是生产者,B是消费者对于响应:A是消费者,B是生产者阻塞队列都是作为交易场所的A和B都只需要关注如何与队列交互优点二:能够对请求进行削峰填谷假设请求突然暴涨A作为入口服务器,计算量轻,问题可能还好但是B作为应用服务器,计算量大,需要的资源系统也多,如果请求更多了,需要资源进一步增加,如果主机的硬件不够,程序就挂了A请求暴涨阻塞队列的请求暴涨由于阻塞队列本来计算量小,只是单纯存数据,所以能抗住更大压力对于B来说,依然按照原来额度速度来消费数据,不会因为A的暴涨二暴涨削峰:这种峰值不是持续的,过去了就恢复了填谷:按照原来哦的频率处理之前挤压的数据3.java标准库的阻塞队列4.自身实现1)实现一个循环队列-底层用数组实现-双指针①.入队列把新元素放到tail的位置上,并且tail②出队列把head位置上上的元素返回回去,并且head③循环当指针head/tail到达数组末尾的时候,就需要从头开始,重新循环④判断空还是满空和满都是head和tail重合1)浪费一个格子,headtail认为是空headtail1认为是满2)额外创建一个变量,size.记录元素额度个数size0 空sizearr.length 满class MyBlockingQueue{//底层用数组实现private int[] arrnew int[1000];//初始化private int size,head,tail;//入队列//实现一个locker类,拥有wait和notify方法private Object lockernew Object();public void put(int a) throws InterruptedException {synchronized(locker){if(sizearr.length){// return;//如果满了就暂时返回locker.wait();}arr[tail]a;size;tail(tail1)%arr.length;//循环队列locker.notify();}}//出队列public Integer take() throws InterruptedException {synchronized (locker){if(size0){//return null;//如果是空的就暂时返回,但是-1明显不高,就把int包装类locker.wait();}int aarr[head];head(head1)% arr.length;size--;locker.notify();return a;}} }注意:2)让队列线程安全保证多线程环境下,调用put和take都是线程安全的但是put和take每一步都是操作公共变量于是我们直接对整个方法加锁实现一个locker类,读写就是locker3)实现阻塞效果关键要点就是使用wait和notify机制对于put来说:阻塞条件,就是队列为满对于take来说:阻塞条件,就是队列为空加锁以后.如果成功take了.就说明不再空了,就可以再take以后唤醒5,实现一个简单的生产者-消费者模型 public static void main(String[] args) {MyBlockingQueue queuenew MyBlockingQueue();Thread producernew Thread(()-{int num0;while (true){try {queue.put(num);System.out.println(生产了num);num;} catch (InterruptedException e) {e.printStackTrace();}}});producer.start();Thread customernew Thread(()-{while(true){try {int tmp queue.take();System.out.println(消费了tmp);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});customer.start();}案例三-定时器像闹钟一样,进行定时,在一定时间之后,被唤醒并执行某个之前设定好的任务1.标准库的的定时器java.util.Timer核心方法 就一个:schedule 参数有两个:任务是什么.多长时间之后执行任务就是一段代码Timer有自己专门的线程,来负责执行注册的任务2.实现一个定时器1)描述任务创建一个专们的类表示定时器的任务(TimerTask)2)组织任务使用一定的数据结构把这些任务放在一起咱们的需求就是,当运行的时候,快速找到所有任务中最小的任务那很明显就是用堆-用带有阻塞的队列因为此处的队列需要考虑到线程安全问题,可能存在多个线程里进行注册任务.同时还有一个专门的任务来执行,所以需要考虑3)执行时间到了的任务需要执行时间最靠前的任务,就需要有个线程,不停地检查当前优先级队首元素看是不是到了4)实现比较器如果要实现自己的类,要接上比较器接口-堆如果是自己的类型,就一定要在自己类里实现自己比较器并接上比较器接口5)解决忙等问题如果不加任何限制,这个循环会执行的非常快如果队列是空的,就会阻塞,如果没空,而且任务时间没到,就会不停地循环这就叫忙等浪费CPU基于wait来实现指定等待时间,计算出当前时间和任务的目标之间的时间差,就等待这么长时间即可到了等待时间就会唤醒问题:既然指定了一个等待时间,为什么不直接用sleep.而用wait呢因为sleep不能被中途唤醒而wait能够被中途唤醒因为在等待过程中,可能要插入新的任务,新的任务很有可能在所有任务之前的比如在schedule操作中,就需要假如一个notify操作一旦有任务进来,就唤醒class MyTask implements ComparableMyTask{//1.描述一个任务private Runnable runnable;//2.描述一个时间private long time;//3.创建一个任务public MyTask(Runnable runnable,long delay){//描述的时间是一个时间jiange,而不是一个确切的时间this.runnablerunnable;this.timeSystem.currentTimeMillis()delay;}public void run(){runnable.run();}public long getTime() {return time;}Overridepublic int compareTo(MyTask o) {return (int)(this.time-o.time);//小根堆} } public class MyTimer {private PriorityBlockingQueueMyTask queuenew PriorityBlockingQueue();private Object lockernew Object();public void schedule(Runnable runnable,long delay){MyTask tasknew MyTask(runnable,delay);queue.put(task);synchronized (locker){locker.notify();}}public MyTimer(){//创建这个线程,看是不是时间到了,该执行任务了Thread tnew Thread(()-{while (true){//先取出队首元素try {MyTask taskqueue.take();long curTimeSystem.currentTimeMillis();//看一下当前时间if(curTimetask.getTime()){queue.put(task);long dectask.getTime()-curTime;synchronized (locker){locker.wait(dec);}}else{task.run();//时间到了,执行}} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}3.总结1.描述一个任务 runabletime2.使用优先级队列来组织若干个任务PriorityBlockingQueue3.实现schedule来注册任务到队列里4.创建个扫描线程,让它不停地获取最小元素,并且判定时间是否到达5.要注意自我创建的类要实现比较器 并且要注意解决这里的忙等问题四.线程池1.原因进程频繁创建销毁,开销比较大,所以我们想到了进程池或者线程线程,虽然比进程轻了.但是如果创建销毁的频率比较多,开销还是有的,解决方案:线程池或协程线程池:把线程提前创建好,放在池子里.后面用到线程直接从池子里取,就不需要在系统申请线程用完了.也不是还给系统.而是放回池子里,以备下次再用这会创建销毁过程,就快很多问题?线程放池子里就比系统申请释放来的快?代码是最上面的应用程序来运行.这里的代码都称为用户态运行的代码创建线程,本身需要内核的支持创建线程的本质就是在内核建立一个PCB(进程控制块)加到链表里所以这是要进入内核态来运行而把创建好玩的线程放到池子里,由于池子就是用户态实现的,这个放到池子/从池子里取的过程,不涉及到内核态,纯粹的用户态代码能够完成一般情况下,纯用户态的操作效率高于经过内核态操作,2.java标准库线程的使用构造方法① int corePoolSize 核心线程数-正式员工的数量② int maximumPoolSize 最大线程数(正式员工临时工) ③ long keepAliveTime 允许临时工摸鱼的时间③TimeUnit unit 时间的单位⑤ BlockingQueue workQueue 任务队列线程池会提供一个submit方法,让程序员把任务注册到线程池中,加入到这个任务队列中⑥ ThreadFactory threadFactory 线程工厂 线程是如何创建的⑦RejectedExecutor handler 拒绝策略当任务队列满了,该怎么做1)直接忽略最新任务,2)阻塞等待,3)直接丢弃最老的任务虽然线程池的参数很多,但是最重要的参数还是线程的个数3.面试问题程序要并发的多线程完成一些任务,如果使用线程池的话,这里的线程池设为多少合适?正确做法:通过性能测试的方式 找到合适的值例如,写一个服务器程序,服务器通过线程池,多线程的处理用户请求就可以对这个服务器进行性能请求,构造一些请求发送给服务器,测试性能,这里的请求就需要构造很多,根据不同的线程池的线程数,来观察程序处理任务的速度和CPU的占用率CPU占用率是很重要的,比如线上服务器,一定要留有一定的冗余,假如请求突然暴涨,如果CPU都快满了,这个时候服务器就会挂了4.自用的线程池Excutors 本质是针对ThreadPoolExecutor进行了封装,提供了一个默认参数要知道线程池里面有什么1)能够描述任务(用Runnable)2)需要一个数据结构组织任务(直接使用BlockingQueue3)能够描述工作线程4)要组织线程5)要能实现往线程池里添加任务class MyThreadPool {// 1. 描述一个任务. 直接使用 Runnable, 不需要额外创建类了.// 2. 使用一个数据结构来组织若干个任务.private BlockingQueueRunnable queue new LinkedBlockingQueue();// 3. 描述一个线程, 工作线程的功能就是从任务队列中取任务并执行.static class Worker extends Thread {// 当前线程池中有若干个 Worker 线程~~ 这些 线程内部 都持有了上述的任务队列.private BlockingQueueRunnable queue null;public Worker(BlockingQueueRunnable queue) {this.queue queue;}Overridepublic void run() {// 就需要能够拿到上面的队列!!while (true) {try {// 循环的去获取任务队列中的任务.// 这里如果队列为空, 就直接阻塞. 如果队列非空, 就获取到里面的内容~~Runnable runnable queue.take();// 获取到之后, 就执行任务.runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}}}// 4. 创建一个数据结构来组织若干个线程.private ListThread workers new ArrayList();public MyThreadPool(int n) {// 在构造方法中, 创建出若干个线程, 放到上述的数组中.for (int i 0; i n; i) {Worker worker new Worker(queue);worker.start();workers.add(worker);}}// 5. 创建一个方法, 能够允许程序猿来放任务到线程池中.public void submit(Runnable runnable) {try {queue.put(runnable);} catch (InterruptedException e) {e.printStackTrace();}} }
http://www.dnsts.com.cn/news/125845.html

相关文章:

  • 网站备案上海如何写网站文案
  • 门户站点是什么长沙官网网站推广优化
  • 哪家公司因为做网站失败了济南百度网站开发
  • 手机好看的网站迪哥哪个网站上做游戏直播
  • 谷歌优化工具上海优化网站公司哪家好
  • 关键词查找网站移动网站制作价格
  • 禅城区做网站策划腾讯云服务器租用
  • 南京做网站的网络公司后台更改公司网站背景图片
  • dede 网站地图模版什么是手机网站
  • 自己公司产品网站的好处网站开发人员绩效如何计算
  • 网站建设费应入什么科目柳州网站网站建设
  • 中国上市公司名单大全东莞债优化
  • 网站介绍模板网络营销的特点与功能
  • 重庆秀山网站建设费用开发大型网站
  • 北京个人网站开发制作wordpress 上传图片错误
  • wordpress全站ajax网站页面设计需求
  • 网站开发项目合同搜索引擎优化技术都有哪些
  • 怎么查询网站点击量搜索引擎推广成功的案例
  • wordpress安装教程桂林seo代排名
  • 榆林网站建设哪家好深圳网站制作需要多少钱
  • 网站平台建设调研报告做外贸哪个网站看外汇
  • 东营做营销型网站设计网名的特殊符号
  • 南平武夷山网站建设无锡网站建设培训班
  • 网站建设公司小程序电信网站备案
  • 表格做网站工装公司联系方式
  • 东营专业网站建设公司电话东莞网站建设电镀挂具
  • 做排版的网站山东住房和城乡建设部网站
  • 小浪底水利枢纽建设管理局网站精神文明地方联盟网站建设
  • 网站集群建设价格泉州网站制作方案
  • 做网站是百度包年快照wordpress中文版和英文版