java培训要学习哪些内容
发布时间:2025-05-19 12:40:27 发布人:远客网络
一、java培训要学习哪些内容
2、Java SE(Java面向对象思想;设计模式、面向对象原则、Java高阶API、线程、网络编程、反射、NIO)
3、Java web(Java web基础、JS、DOM操作、JSP/Servlet、第三方工具包、Tomcat...)
4、框架(网络原理、HTTP协议、Linux操作系统、云服务搭建、SSM框架应用、Oracle应用、Spring JPA、Hibernate...)
5、高可用、高并发、高扩展(SpringBoot、缓存、分布式、插件、全文索引、服务中间件、消息中间件、云服务器、云存储、云数据库、域名服务...)
以下是我们2020年更新的课程,您可以了解一下!
如想学习,可以在我们线上学习平台:百战程序员进行了解!
二、java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列.
2.PriorityQueue,(优先级队列)
3.ConcurrentLinkedQueue,(基于链表的并发队列)
4.DelayQueue,(延期阻塞队列)(阻塞队列实现了BlockingQueue接口)
5.ArrayBlockingQueue,(基于数组的并发阻塞队列)
6.LinkedBlockingQueue,(基于链表的FIFO阻塞队列)
7.LinkedBlockingDeque,(基于链表的FIFO双端阻塞队列)
8.PriorityBlockingQueue,(带优先级的无界阻塞队列)
9.SynchronousQueue(并发同步阻塞队列)
阻塞队列(Blocking queue)提供了可阻塞的put和take方法,它们与可定时的offer和poll是等价的。如果Queue已经满了,put方法会被阻塞直到有空间可用;如果Queue是空的,那么take方法会被阻塞,直到有元素可用。Queue的长度可以有限,也可以无限;无限的Queue永远不会充满,所以它的put方法永远不会阻塞。
阻塞队列支持生产者-消费者设计模式。一个生产者-消费者设计分离了“生产产品”和“消费产品”。该模式不会发现一个工作便立即处理,而是把工作置于一个任务(“to do”)清单中,以备后期处理。生产者-消费者模式简化了开发,因为它解除了生产者和消费者之间相互依赖的代码。生产者和消费者以不同的或者变化的速度生产和消费数据,生产者-消费者模式将这些活动解耦,因而简化了工作负荷的管理。
生产者-消费者设计是围绕阻塞队列展开的,生产者把数据放入队列,并使数据可用,当消费者为适当的行为做准备时会从队列中获取数据。生产者不需要知道消费者的省份或者数量,甚至根本没有消费者—它们只负责把数据放入队列。类似地,消费者也不需要知道生产者是谁,以及是谁给它们安排的工作。BlockingQueue可以使用任意数量的生产者和消费者,从而简化了生产者-消费者设计的实现。最常见的生产者-消费者设计是将线程池与工作队列相结合。
阻塞队列简化了消费者的编码,因为take会保持阻塞直到可用数据出现。如果生产者不能足够快地产生工作,让消费者忙碌起来,那么消费者只能一直等待,直到有工作可做。同时,put方法的阻塞特性也大大地简化了生产者的编码;如果使用一个有界队列,那么当队列充满的时候,生产者就会阻塞,暂不能生成更多的工作,从而给消费者时间来赶进进度。
有界队列是强大的资源管理工具,用来建立可靠的应用程序:它们遏制那些可以产生过多工作量、具有威胁的活动,从而让你的程序在面对超负荷工作时更加健壮。
虽然生产者-消费者模式可以把生产者和消费者的代码相互解耦合,但是它们的行为还是间接地通过共享队列耦合在一起了
类库中包含一些BlockingQueue的实现,其中LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列,与 LinkedList和ArrayList相似,但是却拥有比同步List更好的并发性能。PriorityBlockingQueue是一个按优先级顺序排序的队列,当你不希望按照FIFO的属性处理元素时,这个PriorityBolckingQueue是非常有用的。正如其他排序的容器一样,PriorityBlockingQueue可以比较元素本身的自然顺序(如果它们实现了Comparable),也可以使用一个 Comparator进行排序。
最后一个BlockingQueue的实现是SynchronousQueue,它根本上不是一个真正的队列,因为它不会为队列元素维护任何存储空间。不过,它维护一个排队的线程清单,这些线程等待把元素加入(enqueue)队列或者移出(dequeue)队列。因为SynchronousQueue没有存储能力,所以除非另一个线程已经准备好参与移交工作,否则put和take会一直阻止。SynchronousQueue这类队列只有在消费者充足的时候比较合适,它们总能为下一个任务作好准备。
基于锁的算法会带来一些活跃度失败的风险。如果线程在持有锁的时候因为阻塞I/O,页面错误,或其他原因发生延迟,很可能所有的线程都不能前进了。
一个线程的失败或挂起不应该影响其他线程的失败或挂起,这样的算法成为非阻塞(nonblocking)算法;如果算法的每一个步骤中都有一些线程能够继续执行,那么这样的算法称为锁自由(lock-free)算法。在线程间使用CAS进行协调,这样的算法如果能构建正确的话,它既是非阻塞的,又是锁自由的。非竞争的CAS总是能够成功,如果多个线程以一个CAS竞争,总会有一个胜出并前进。非阻塞算法堆死锁和优先级倒置有“免疫性”(但它们可能会出现饥饿和活锁,因为它们允许重进入)。
非阻塞算法通过使用低层次的并发原语,比如比较交换,取代了锁。原子变量类向用户提供了这些底层级原语,也能够当做“更佳的volatile变量”使用,同时提供了整数类和对象引用的原子化更新操作
三、java阻塞队列 线程同步合作
1、 Queue接口与List Set同一级别都是继承了Collection接口 LinkedList实现了Queue接口 Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时就完全只能访问Queue接口所定义的方法了而不能直接访问 LinkedList的非Queue的方法)以使得只有恰当的方法才可以使用 BlockingQueue继承了Queue接口
2、队列是一种数据结构.它有两个基本操作在队列尾部加人一个元素和从队列头部移除一个元素就是说队列以一种先进先出的方式管理数据如果你试图向一个已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索将导致线程阻塞.在多线程进行合作时阻塞队列是很有用的工具工作者线程可以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们队列会自动平衡负载如果第一个线程集运行得比第二个慢则第二个线程集在等待结果时就会阻塞如果第一个线程集运行得快那么它将等待第二个线程集赶上来下表显示了jdk中的阻塞队列的操作
3、 add增加一个元索如果队列已满则抛出一个IIIegaISlabEepeplian异常
4、 remove移除并返回队列头部的元素如果队列为空则抛出一个NoSuchElementException异常
5、 element返回队列头部的元素如果队列为空则抛出一个NoSuchElementException异常
6、 offer添加一个元素并返回true如果队列已满则返回false
7、 poll移除并返问队列头部的元素如果队列为空则返回null
8、 peek返回队列头部的元素如果队列为空则返回null
9、 put添加一个元素如果队列满则阻塞
10、 take移除并返回队列头部的元素如果队列为空则阻塞
11、 remove element offer poll peek其实是属于Queue接口
12、阻塞队列的操作可以根据它们的响应方式分为以下三类 aad removee和element操作在你试图为一个已满的队列增加元素或从空队列取得元素时抛出异常当然在多线程程序中队列在任何时间都可能变成满的或空的所以你可能想使用offer poll peek方法这些方法在无法完成任务时只是给出一个出错示而不会抛出异常
13、注意 poll和peek方法出错进返回null因此向队列中插入null值是不合法的
14、还有带超时的offer和poll方法变种例如下面的调用
15、 boolean success= q offer(x TimeUnit MILLISECONDS);
16、尝试在毫秒内向队列尾部插入一个元素如果成功立即返回true否则当到达超时进返回false同样地调用
17、 Object head= q poll( TimeUnit MILLISECONDS);
18、如果在毫秒内成功地移除了队列头元素则立即返回头元素否则在到达超时时返回null
19、最后我们有阻塞操作put和take put方法在队列满时阻塞 take方法在队列空时阻塞
20、 ncurrent包提供了阻塞队列的个变种默认情况下 LinkedBlockingQueue的容量是没有上限的(说的不准确在不指定时容量为Integer MAX_VALUE不要然的话在put时怎么会受阻呢)但是也可以选择指定其最大容量它是基于链表的队列此队列按 FIFO(先进先出)排序元素
21、 ArrayBlockingQueue在构造时需要指定容量并可以选择是否需要公平性如果公平参数被设置true等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来达到这种公平性的即等待时间最长的线程会先操作)通常公平性会使你在性能上付出代价只有在的确非常需要的时候再使用它它是基于数组的阻塞循环队列此队列按 FIFO(先进先出)原则对元素进行排序
22、 PriorityBlockingQueue是一个带优先级的队列而不是先进先出队列元素按优先级顺序被移除该队列也没有上限(看了一下源码 PriorityBlockingQueue是对PriorityQueue的再次包装是基于堆数据结构的而PriorityQueue是没有容量限制的与ArrayList一样所以在优先阻塞队列上put时是不会受阻的虽然此队列逻辑上是无界的但是由于资源被耗尽所以试图执行添加操作可能会导致 OutOfMemoryError)但是如果队列为空那么取元素的操作take就会阻塞所以它的检索操作take是受阻的另外往入该队列中的元素要具有比较能力
23、最后 DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed元素的无界阻塞队列只有在延迟期满时才能从中提取元素该队列的头部是延迟期满后保存时间最长的 Delayed元素如果延迟都还没有期满则队列没有头部并且poll将返回null当一个元素的 getDelay(TimeUnit NANOSECONDS)方法返回一个小于或等于零的值时则出现期满 poll就以移除这个元素了此队列不允许使用 null元素下面是延迟接口
24、 public interface Delayed extends Comparable<Delayed>{
25、 long getDelay(TimeUnit unit);
26、 public interface Delayed extends Comparable<Delayed>{
27、 long getDelay(TimeUnit unit);
28、放入DelayQueue的元素还将要实现pareTo方法 DelayQueue使用这个来为元素排序
29、下面的实例展示了如何使用阻塞队列来控制线程集程序在一个目录及它的所有子目录下搜索所有文件打印出包含指定关键字的文件列表从下面实例可以看出使用阻塞队列两个显著的好处就是多线程操作共同的队列时不需要额外的同步另外就是队列会自动平衡负载即那边(生产与消费两边)处理快了就会被阻塞掉从而减少两边的处理速度差距下面是具体实现
30、 public class BlockingQueueTest{
31、 public static void main(String[] args){
32、 Scanner in= new Scanner(System in);
33、 System out print( Enter base directory(e g/usr/local/jdk/src):);
34、 String directory= in nextLine();
35、 System out print( Enter keyword(e g volatile):);
36、 String keyword= in nextLine();
37、 final int FILE_QUEUE_SIZE=;//阻塞队列大小
38、 final int SEARCH_THREADS=;//关键字搜索线程个数
39、//基于ArrayBlockingQueue的阻塞队列
40、 BlockingQueue<File> queue= new ArrayBlockingQueue<File>(
41、 FileEnumerationTask enumerator= new FileEnumerationTask(queue
42、 new Thread(enumerator) start();
43、//启动个线程用来在文件中搜索指定的关键字
44、 for(int i=; i<= SEARCH_THREADS; i++)
45、 new Thread(new SearchTask(queue keyword)) start();
46、 class FileEnumerationTask implements Runnable{
47、//哑元文件对象放在阻塞队列最后用来标示文件已被遍历完
48、 public static File DUMMY= new File();
49、 private BlockingQueue<File> queue;
50、 private File startingDirectory;
51、 public FileEnumerationTask(BlockingQueue<File> queue File startingDirectory){
52、 this startingDirectory= startingDirectory;
53、 enumerate(startingDirectory);
54、 queue put(DUMMY);//执行到这里说明指定的目录下文件已被遍历完
55、} catch(InterruptedException e){
56、//将指定目录下的所有文件以File对象的形式放入阻塞队列中
57、 public void enumerate(File directory) throws InterruptedException{
58、 File[] files= directory listFiles();
59、//将元素放入队尾如果队列满则阻塞
60、 class SearchTask implements Runnable{
61、 private BlockingQueue<File> queue;
62、 public SearchTask(BlockingQueue<File> queue String keyword){
63、//取出队首元素如果队列为空则阻塞
64、 if(file== FileEnumerationTask DUMMY){
65、//取出来后重新放入好让其他线程读到它时也很快的结束
66、} catch(InterruptedException e){
67、 public void search(File file) throws IOException{
68、 Scanner in= new Scanner(new FileInputStream(file));
69、 System out printf(%s:%d:%s%n file getPath() lineNumber