Java线程和并发工具
文章平均质量分 67
Owen William
这个作者很懒,什么都没留下…
展开
-
解决系统性能问题:线程增加导致堆增加
问题描述最近使用Spring boot 架构了一套监控系统.由于是监控系统,所以对系统的调用频率会比较频繁。例如,系统要每隔30秒开启线程去访问远程主机获取所需要的信息。所以系统的开销还是比较大。就是因为开销大,所以要保证系统自身不能卡死,不然还怎么去监控其它的呢?但是事与愿违,这套监控系统刚开始跑个两三天是没有问题的,后来发现,重启系统后,运行一个小时多就卡死了。前端访问不到页面,控制台报错...原创 2019-07-23 09:25:26 · 1127 阅读 · 1 评论 -
7.4读写锁(ReadWriteLock)
数据结构比起修改更为常见的是读取的情况。例如,你可能创建一个在线和字典,定义许多线程将会同时进行读,在些期间一个信息线程可能会添加新的定义或更新定义。在高并发的情况,要读和安全的执行写,锁框架提供了读写锁的机制。这个机制就是以ReadWriteLock为基础的接口。 ReadWriteLock是一对锁:一个锁是仅仅给读操作和另一个锁是仅仅给写操作。读写锁在多个读的线程中可以会被同时持翻译 2017-12-30 22:14:55 · 248 阅读 · 0 评论 -
7.3 环境(Condition)
环境(Condition)因素对对象的等待和通知方法(waite(),notify()和notifyall()方法)作为不同的状态对象,给这些对象的多个等待集合的影响。这里我们用锁(Lock)取代同步(synchronize)方法和阻塞,环境(Condition)取代对象的等待(wait)和唤醒(notifycation)的方法。 Note 环境(Condition)实例本质上翻译 2017-12-30 22:12:51 · 369 阅读 · 0 评论 -
7.2 重入锁(ReentrantLock)
锁(Lock)通过应用重入锁(ReentrantLock)的类,它将使用的是重入的互斥锁。这个锁连接着一个持有计数。当一个线程持有锁,和请求锁通过执行lock()、lockUninterruptibly()或其中一个tryLock()方法时,持有计数就会加1。当线程执行unlock()的方法时,这个持有计数就会减1.当计数为0时,锁就会释放。 重入锁(ReentrantLock)提供翻译 2017-12-30 22:10:19 · 266 阅读 · 0 评论 -
7.1 锁(Lock)
锁的接口提供许多可扩展的锁应用,而它包含经过锁关联的监测器。例如,当一个锁没有用时,你可以快速撤消锁的获取。这个接口声明了如下的方法: void lock():请求锁。当锁没有作用时,请求线程会处于强迫等待状态直到锁可以用。 void lockInterruptibly():请求等到锁,除非请求的线程被打断。当请求的锁不可用时,请求的线程会处于被迫等待状态,直到它变成可用。翻译 2017-12-30 22:08:05 · 293 阅读 · 0 评论 -
7. 锁定框架(The Locking Framework)
java.util.concurrent.locks的包提供一个接口和类的接口,主要用于在方法中正在锁住和等待的状态,这个状态来自于同步锁的基础和java.lang.Object的等待和唤醒的机制。并发的工具包含锁的框架,它通过锁池和等待时间等等以提高锁和等待唤醒机制。java提供同步机制,以至于线程可以安全地更新和分享变量,和确保一个线程的安全对于其它线程是有效的。你在自己的代码将同步用翻译 2017-12-30 22:07:08 · 363 阅读 · 0 评论 -
6.6总结
java为同步线程访问关键部分提供了synchronized关键字。基于代码同步和高级同步者包含并发工具是很难写出正确的同步代码。 一个countdown latch导致一个或多个线处于“门”外等待,直到其它线程为它开户这个门,而关键的是其它线程可以正常继续。它包含着一个计数和操作,操作当前的线程等待直到计数为0 ,计数是在递减的。 一个循环的障碍(cyclicbarrie翻译 2017-12-30 22:05:43 · 231 阅读 · 0 评论 -
6.5移相器(Phasers)
移相器(phaser)是一个更加灵活的循环障碍。像一个循环的障碍,一个移相器(phaser)让一组在等待的线程处于障碍中,在最新线程到达之前,这些线程会继续处于障碍。一个移相器(phaser)提供相同的障碍动作。不像一个循环的障碍,它维持着一个固定数量的线程。一个移相器(phaser)可以维持着多样的数量的线程,它可以在任何时间注册。为了去应用这个的功能,一个移相器会应用移相或移相数据。翻译 2017-12-30 22:03:14 · 3430 阅读 · 0 评论 -
6.4信号灯(Semaphores)
一个semaphore保持着许可,让线程受到束缚,限制它们的资源。一个线程通过请求一个许可,当没有许可时,要等待其它线程释放一个许可。 Note semaphore的当前值可以递增近1,被称为计数semaphore。而semaphore的值只能为0或1,被称为二进制的semaphore、互斥。在这两种情况下,当前值不能为负1。java.util.concurrent.翻译 2017-12-30 21:59:34 · 348 阅读 · 0 评论 -
6.3交换器(Exchangers)
一个exchanger提供一个同步的点,这个会擦除对象。每一个在记录中出现的对象,都会去执行exchanger的exchange()的方法,匹配它的父线程,和接收返回父对象返回值。Exchanger在实际应用中很有作用,像遗传算法和流水线设计。 java.util.concurrent.Exchanger继承exchanger的同步者。你可以执行Exchanger()的构造器初始化一个翻译 2017-12-30 21:58:45 · 386 阅读 · 0 评论 -
6.2阻碍循环(Cyclic Barriers)
一个cyclicbarrier让一堆的线程处于等待状态,它们彼此之间会有相同的阻碍点。这个阻碍是循环的,因为当等待的线程等到释放且,它可能会被重复利用。这个同步器在应用的程序中是非常有用的,它会执行一个固定大小的线程,偶尔必须等待每一个线程。 java.util.concurrent.CyclicBarrier类继续一个循环的阻碍同步器。你可以通过执行这个类的CyclicBarrier翻译 2017-10-14 17:09:52 · 429 阅读 · 0 评论 -
6.1倒计时锁(Countdown Latches)
Countdown Latches会让一个或多个线程处于等待,直到其它线程为它开户“门”;也就是说有空闲的线程出现才行。关键还是在于这些其它的线程会一直执行下去。Countdown Latches是有一个计数器,它会让线程处于等待状态直到计算达到‘0’,而这个计数是在递减的。 java.util.concurrent.CountDownLatch继承countdown latch的同步翻译 2017-10-14 17:07:01 · 732 阅读 · 0 评论 -
7.5重入读写锁( ReentrantReadWritelock)
ReadWriteLock是继承ReantrantReadWriteLock的类,这就声明了一个重入读写锁,有点类似于ReentrantLock. 你可以通过以下的方法来初始化ReentrantReadWriteLock的实例。 ReentrantReadWriteLock():创建一个ReentrantReadWriteLock的实例。这个构造器类似于Ree翻译 2017-12-30 22:15:53 · 373 阅读 · 0 评论 -
8.5总结
这一章节介绍了并发集合(concurrent collections)、原子变量(atomic variables)、分叉/结合的框架(Fork/Join Framework)和完成服务(completion services)。 一个并发集合是一个并发的应用和高调度的集合面向这些储蓄在java.util.concurrent的包。它克服了ConcurrentModificationE翻译 2018-01-29 22:44:10 · 222 阅读 · 0 评论 -
8.4完成服务(Completion Services)
completion services是一个java.util.concurrent.CompletionService接口的应用,这个是从同步任务和从任务完成的返回结果中解耦。V是任务返回的类型。 一个生产者提交一个任务执行(通过一个工作线程),通过请求一个submit()方法:一个方法接受可调用的参数和一个方法接受运行中的参数随后结果返回任务的完成。为了任务的完成,你可以从池中请求翻译 2018-01-29 22:42:49 · 482 阅读 · 0 评论 -
8.3分叉/结合的框架(Fork/Join Framework)
我信总是需要让我们的代码执行更快。过去,我们需要依赖于微处理器的速度提升和通过提供多处理器。然而,大概在2003年,微处理器的速度停止提升,因为自然因素的限制。为了弥补这个不足,我们需要人工的处理器去添加多处理核,这样就可以在高度并发性中提升速度。 Java通过低级的线程提供并发的应用,和高级的并发工具应用如线程池。问题是并发不能最大的使用变量处理器或核的资源。例如,假定你创建一个排翻译 2018-01-29 22:41:26 · 302 阅读 · 0 评论 -
8.2.1理解原子
java的低级同步机制,它强调了线程间互相执行(当前线程持有锁,并且有一堆的变量在这个线程中执行)和可测量性(让守护的变量成为其它线程可用,并且随后申请锁)。在以下的方式中影响着硬件的性能和可扩展性: 竞争同步(多个线程不断地竞争一个锁)是昂贵的,和吞吐量影响着结果。这个昂贵的代价主要是因为频繁的上下文件有切换(选择一个中心的进程直到一个线程到另一个线程)。每一个上下文的选择操作会计翻译 2018-01-29 22:37:46 · 238 阅读 · 0 评论 -
8.2原子变量
在原有的锁连接着一个监测器,在以往使用中表现不佳。尽管在性能上有得到提升,但是在互联网的服务器和其它频繁请求的应用中还是遇到瓶颈。 大量的探索中,找到了一个创建无锁的算法,这个算法可以在同步的应用中提高应用性能。这些算法提高了可扩展性,因为在多线程的相同数据处理中,不需要在线程中加锁。因此,这样就不会出现死锁或线程死掉的问题。 Java5通过使用java.util.conc翻译 2018-01-29 22:35:38 · 269 阅读 · 0 评论 -
8.1.2 学习更多关于ConcurrentHashMap
ConcurrentHashMap类的行为就像是HashMap,但是它设计工作在多线程中不需要明确同步。例如,你需要去检查map中是否包含着特殊的值,如下:if (!map.containsKey("some string-based key"))map.put("some string-based key", "some string-based value"); 尽管这个翻译 2018-01-29 22:32:54 · 209 阅读 · 0 评论 -
8.1.1使用BlockingQueue和ArrayBlockingQueue
使用BlockingQueue来实现产生都与消费者的例子,比起前面第三章的用法会更加简单,因为它不需要去解决同步问题。下面的例子使用BlockingQueue和ArrayBlockingQueue实现生产者的消费者的例子。package com.owen.thread.chapter8;import java.util.concurrent.ArrayBlockingQueue;impo翻译 2018-01-29 22:30:58 · 313 阅读 · 0 评论 -
8.1并发集合(Concurrent Collections)
Java并发框架在包java.util.package中提供了接口和类。接口中包含List、Set和Map;类包含了ArrayList、TreeSet和HashMap。 ArrayList、TreeSet、HashMap和其它的类都继承了这些类接口,但是它们是不安全的线程。然而,你可以让它们在使用是安全的线程,通过使用java.util.Collection类的同步擦除方法。例如翻译 2018-01-29 22:29:30 · 469 阅读 · 0 评论 -
8. 额外的并发实用程序(Additional Concurrency Utilities)
在前面的几个章节中,我已经介绍了并发工具(concurrency utilities)、执行(executors)、同步者(snychronizer)和锁的框架(Locking Framework)。在这一章节,我将介绍并发集合(concurrent collections)、原子变量(atomic variable)、分叉/合并框架(Fork/Join Framework)和完成服务(compl翻译 2018-01-29 22:25:53 · 286 阅读 · 0 评论 -
7.6 总结
java.util.concurrent包提供接口框架,和给环境(Condition)的方法等待、锁的类,这些都是基于同步锁和对象等待、唤醒的机制。并发工具包括锁的框架,促进我们在同步和等待、唤醒中提供锁等待轮询。 锁的框架包含了我们经常使用的Lock、Reentrantlock、Condition、ReadWriteLock和ReentrantReadWriteLock,这些在这个章翻译 2018-01-29 22:24:51 · 199 阅读 · 0 评论 -
6. 同步化器(Synchronizers)
Java提供了同步的关键字给同步线程,是一个极其关键的部分。因为在并发的工具类里,包含着synchronized、高级的synchronizers(这个类有助于普通形式类的同步),可以更容易地、正确地写出同步的代码。在这一章节里,我将同你介绍countdown latch、cyclic barrier、exchanger、semaphore和phaser的同步对象。翻译 2017-10-14 17:06:17 · 509 阅读 · 0 评论 -
5.3总结
java的低级线程的性能方法,不足以让你在单线程的计算机上,运行多线程的应用,或更好表现出应用性能。因此,导致Java5设计出了并发的工具应用。 并发的工具主是位于三个包:java.util.concurrent、java.util.concurrent.atomic和java.util.concurrent.locks。executors的基础风格、threadpool(线程池)、c翻译 2017-10-14 17:05:26 · 209 阅读 · 0 评论 -
5.2探究执行器(Executors)
你可以通过java提供的线程API来执行任务,像创建一个java.lang.Thread(newRunnableTask()).start();这个应用在可以执行多任务的机器表现更为明显(运行当前线程,创建线程和在线程池中随意选择执行线程)。 Note 一个任务就是一个对象,它会继承java.lang.Runnable的接口(执行的任务)或者继承java.util.concu原创 2017-10-14 17:02:56 · 359 阅读 · 0 评论 -
1.2.3休眠(Sleeping)
Thread类声明一对static方法让线程处于休眠状态: (1)void sleep(long millis):休眠millis毫秒。线程休眠的实际毫秒数取决于系统定时器和调度程序的精度和准确性。当millis不合法,将会抛出IllegaArgumentException异常;当任何线程的当前线程被打断,将会抛出IllegaArgumentException异常。当这个异常抛出翻译 2017-06-04 18:32:54 · 590 阅读 · 0 评论 -
1.2.2合并线程(Joining Threads)
一个线程(像主线程)有时候需要开始一个其它线程去执行大量数据的计算、下载文件或执行耗时的活动。在完成其它任务之后,这个线程就会开始工作线程,而这个工作线程已经准备好了去执行工作线程的结果返回和等待工作线程完成和死亡。 Thread提供三个join()方法,这个方法允许线程去等待其它线程,谁调用了object join()方法谁就会死亡。 void join():无限期等翻译 2017-06-04 18:31:15 · 577 阅读 · 0 评论 -
1.2执行更高级的线程任务(Performing More Advanced Thread Tasks)
这个Thread提供给每一个线程可以打断另一个线程的打断机制。当一个线程被打断,它将会抛出java.lang.InterruptedException的异常。这个机制包含了下面三个的方法: void interrupt():通过Thread的这个方法来打断一个线程。当一个线程因为请求Thread的sleep()或join()的方法而阻塞时,这个线程被打断将会抛出Interrupt翻译 2017-06-04 18:28:40 · 641 阅读 · 0 评论 -
1.1.3开启线程(Starting a Thread)
1.1.3开启线程(Starting a Thread) 之后创建一个Thread或Thread的子类对象,你可以通过Thread的void start()的方法请求开启线程连接对象。当线程已经存在和它存在运行或线程已经死亡,那么会抛出java.lang.IllegalThreadStateException的异常。Thread t = new Thread(r);t.sta翻译 2017-05-30 18:29:04 · 647 阅读 · 0 评论 -
1.1.2获取和控制线程状态(Getting and Seeting Thread State)
1.1.2获取和控制线程状态(Getting and Seeting Thread State)一个线程对象联合着一个线程的状态。这个状态包含着一个名字、一个表明线程是活着还是死着、执行线程的状态(它是否在执行?)、线程的优先权、声明线程是守护进程还是非守护进程。1.1.2.1获取和控制一个线程的名字(Getting and Setting a Thread’s Name)一个Thre翻译 2017-05-30 18:25:08 · 719 阅读 · 0 评论 -
1.1介绍线程和运行(Introducing Thread and Runnable)
线程类提供了线程结构,其中包含了潜在地去操作系统的接口。(这个操作通常是请求创建和管理线程。)一个单一的操作系统线程也连接着一个Thread对象。Runnable接口提供通过线程执行的代码,它也连接着一个Thread对象。这个代码位于Runnbale的void run()方法——一个线程没有接收参数和返回值,尽管它可能抛出异常。1.创建Thread和Runnable对象 除了默认的翻译 2017-05-30 18:19:24 · 484 阅读 · 0 评论 -
第一部分 线程APIs(Thread APIs)线程和运行(Threads and Runnables)
Java的应用执行通过多个线程的作用,它们主要依赖于执行的路径,而该路径就是应用的代码。当多个线程正在执行时,每一个线程的路径可以是与其它线程的路径不同。例如,一个线程可能执行一个Switch的语句,而其它的线程可能执行这个语句的cases语句。 每一个Java的应用都有一个默认的主线程,也就是执行main()的方法。这个应用也可以创建线程给时间密集的任务,而其任务可能是放到后台执行,翻译 2017-05-30 18:14:52 · 600 阅读 · 0 评论 -
2.5总结
当线程之间不会相互作用时,提高多线程性能是非常容易的,尤其是通过共享变量。当线程之间相互作用出现、竞争状态、数据竞争和缓存变量问题会提高一个应用的线程不安全性。你可以使用同步去解决竞争状态、数据竞争和缓存变量问题。同步是一个java虚拟机的特性,它确保两个或更多当前线程不会同时执行一个临界区,必须有序列地进行。活跃性涉及最终以有利的方面结束应用。当一个应用的状态是不能继续往下执行时,那么活翻译 2017-07-16 18:33:56 · 246 阅读 · 0 评论 -
2.4变动和最终变量(Volatile and Final Variables)
在前面的学习同步锁显示了两个属性:互斥和可见性。同步关键字连接着这两个属性。Java提供一个弱引用的仅仅用于同步可见性。它也连接着一个volatile的关键字。假设你设计一个机制去停止一个线程(因为你不能用Thread的stop()方法,在这个任务中它是不安全的)。Listing2-2显现出了代码资源并于ThreadStoping的应用,和展示了你可能完成的任务。Listing2-2p翻译 2017-07-16 18:32:49 · 511 阅读 · 0 评论 -
2.3谨慎活跃问题(Beware of Liveness Problems)
活跃指的是一些最终以有利方面结束。当一个应用到达的状态是为不可能继续向下执行时,那么就是非活跃的。在单一线程应用中,死循环就是一个例子。在多线程的应用中,活跃是死锁、活锁和饥饿: Deadlock:线程1等待的资源是线程2所持有的,和线程2等待资源是线程1所持有的。两个线程会同时在等待。 LiveLock:线程x保持着尝试一个操作,而这个总是失败。这个的情况是不翻译 2017-07-16 18:27:47 · 361 阅读 · 0 评论 -
2.2同步访临界区(Synchronizing Access to Critical Section)
你可以使用同步去解决前面线程问题。Synchronization是Java虚拟机的一个特性,它可以确保两个或更多的线程不会同时执行一个临界区(a critical section),这个代码部分必须按一定的顺序来调用(一个时间段,只有一个线程执行)。 这个同步属性就是我们所知道的互斥,因为当另一个线程在临界区时,每个线程临界区相互排斥。对于这个的原因,线程的请求经常涉及到互斥锁。同翻译 2017-07-16 18:23:56 · 338 阅读 · 0 评论 -
1.3总结
Java的应用执行是通过线程的,它依赖于应用代码执行的路径。每一个Java的应用都有一个默认的主线程执行main()的方法。这个应用也可以创建线程去执行时间密集的任务,而且是在后台执行,以至于它保留着用户的影响。这个执行代码是封装在对象中的,也说是我们所知道的runnable. Thread类提供了与底层操作系统的线程结构一致的接口。(操作系统通常负责创建和管理线程)。一个操作系统线程与翻译 2017-06-04 18:33:51 · 360 阅读 · 0 评论 -
3.等待和通知(Waiting and Notification)
java提供了一个API,支持线程之间通信。运用这个API,一个线程等待条件是存在的(前提是继续执行)。这个特性,其它线程将会创建一个状态和通知等待的线程。这一章节,我们将介绍这个API。 源码下载:Git@github.com:owenwilliam/Thread.git翻译 2017-07-23 21:00:55 · 370 阅读 · 0 评论 -
5.并发工具和执行器(Concurrency Utilities and Executors)5.1 并发工具介绍
5.1并发工具介绍 java简单的线程可以满足你去创建多线程的应用,相对单线程来说,java的简单线程的接口应用还是有一定的代表性的。可是那些简单的应用却有如下的问题: java的简单并发工具应用经常不能够被正确使用,如synchronized和wait()/notify()的工具。这些不正确的工具使用,或说早期的工具会用,将会导致线程间的竞争的现象中出现如翻译 2017-10-14 17:00:59 · 350 阅读 · 0 评论