线程

线程中会有的问题

ぐ巨炮叔叔 提交于 2020-03-25 19:16:30
1 . 什么是Java线程转储(Thread Dump),如何得到它? 线程转储是一个 JVM活动线程的列表,它对于分析系统瓶颈和死锁非常有用。有很多方法可以获取线程转储——使用Profiler,Kill -3命令,jstack工具等等。我更喜欢jstack工具,因为它容易使用并且是JDK自带的。由于它是一个基于终端的工具,所以我们可以编写一些脚本去定时的产生线程转储以待分析。 2. 什么是死锁(Deadlock)?如何分析和避免死锁? 死锁是指两个以上的线程永远阻塞的情况,这种情况产生至少需要两个以上的线程和两个以上的资源。 分析死锁,我们需要查看 Java应用程序的线程转储。我们需要找出那些状态为BLOCKED的线程和他们等待的资源。每个资源都有一个唯一的id,用这个id我们可以找出哪些线程已经拥有了它的对象锁。 3 . 什么是Java Timer类?如何创建一个有特定时间间隔的任务? java.util.Timer是一个工具类,可以用于安排一个线程在未来的某个特定时间执行。Timer类可以用安排一次性任务或者周期任务。 java.util.TimerTask是一个实现了Runnable接口的抽象类,我们需要去继承这个类来创建我们自己的定时任务并使用Timer去安排它的执行。 4 . 什么是原子操作?在Java Concurrency API中有哪些原子类(atomic

面试必备之乐观锁与悲观锁

醉酒当歌 提交于 2020-03-25 19:09:34
何谓悲观锁与乐观锁 乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。 乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。 两种锁的使用场景 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候

Java 中的协程库 - Quasar

早过忘川 提交于 2020-03-25 18:33:14
一、协程 一个进程可以产生许多线程,每个线程有自己的上下文,当我们在使用多线程的时候,如果存在长时间的 I/O 操作,线程会一直处于阻塞状态,这个时候会存在很多线程处于空闲状态,会造成线程资源的浪费。这就是协程适用的场景。 协程,其实就是在 一个线程 中,有一个总调度器,对于多个任务,同时只有一个任务在执行,但是一旦该任务进入阻塞状态,就将该任务设置为挂起,运行其他任务,在运行完或者挂起其他任务的时候,再检查待运行或者挂起的任务的状态,使其继续执行。 协程的方式更多用来做阻塞密集型(比如 I/O)的操作,计算密集型的还是使用线程更加合理。 Java 官方并没有协程库。但是伟大的社区提供了一个优秀的库,它就是 Quasar。 二、Quasar 简介 Quasar 提供了高性能轻量级的线程,提供了类似 Go 的 channel,Erlang 的 actor,以及其它的异步编程的工具,可以用在 Java 和 Kotlin 编程语言中。 Quasar 最主要的贡献就是提供了轻量级线程的实现 —— fiber。Fiber 的功能和使用类似 Thread, API 接口也类似,所以使用起来没有违和感,但是它们不是被操作系统管理的,它们是由一个或者多个 ForkJoinPool 调度。一个空闲的 fiber 只占用 400 字节内存,切换的时候占用更少的 CPU,你的应用中可以有上百万的

java中锁的概念

北慕城南 提交于 2020-03-25 16:40:28
可重入锁(递归锁) 本文里面讲的是广义上的可重入锁,而不是单指 JAVA 下的 ReentrantLock。可重入锁,也叫做递归锁,指的是 同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响 。在 JAVA 环境下 ReentrantLock 和 synchronized 都是 可重入锁。当然有可重入锁就有不可重入锁,不可重入锁就是 同一线程 外层函数获得锁之后 ,只能当前函数使用 package com.yjc.juc; import java.util.concurrent.locks.ReentrantLock; class ZiYuan { ReentrantLock reentrantLock = new ReentrantLock(); public void method1() { reentrantLock.lock(); try { System.out.println("进入方法1"); System.out.println("准备调用方法2"); method2(); } catch (Exception e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } } public void method2() { reentrantLock.lock(); try

线程安全问题

本小妞迷上赌 提交于 2020-03-25 15:45:51
本文楼主主要以用户在售票厅购买车票为背景进行多线程的实现。假设A市到B市的车票共50张,共有3个售票窗口在进行售票,使用多线程来模拟理想情况下的用户购票: 实现Runnable的Ticket类: 1 package com.jon.thread; 2 3 public class TicketSell implements Runnable { 4 private int tickets = 50;//设置车票数量 5 @Override 6 public void run() { 7 while(true){ 8 if(tickets>0){ 9 //输出当前是哪个线程在出售第几张车票 10 System.out.println(Thread.currentThread().getName() + "正在售第" + (tickets--) + "张车票"); 11 } 12 } 13 } 14 15 } 简单的售票业务构建好后,我们用三个线程模拟售票窗口来进行测试: 1 package com.jon.thread; 2 3 public class TicketSellTest { 4 public static void main(String[] args) { 5 TicketSell ts = new TicketSell(); 6 Thread td1 = new

同步异步和阻塞非阻塞

六眼飞鱼酱① 提交于 2020-03-25 15:45:12
一、同步与异步 : 重点是是否强调事件发生的顺序:请求发出后,是否需要等待请求结果,才能继续执行其他操作。 1. 同步:同步就是发起一个请求,直到请求返回结果之后,才进行下一步操作。简单来说,同步就是必须一件事一件事的做,等前一件做完了,才能做下一件事。 核心:Java主动读写数据,进行IO操作。 2. 异步:当一个异步操作发出后,调用者在没有得到结果之前,可以继续执行后续操作。 核心:Java委托给内核(OS)完成读写操作,并且通知Java读写完成。 二、阻塞与非阻塞 : 重点在程序等待结果时的状态:进程/线程需要操作的数据如果尚未就绪,是否妨碍了当前进程/线程的后续操作。 1. 阻塞:在调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会被唤醒执行后续的操作。 2. 非阻塞:在结果没有返回之前,该调用不会阻塞住当前线程。 三、之间的联系 在处理IO时,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO。 来源: https://www.cnblogs.com/kikis/p/10715189.html

nio--自己总结

纵饮孤独 提交于 2020-03-25 15:42:29
阻塞/非阻塞 + 同步/异步 其实,这两者存在本质的区别,面向的对象是不同的。 阻塞/非阻塞:进程/线程需要操作的数据如果尚未就绪, 是否妨碍了当前进程/线程的后续操作 。 同步/异步:数据如果尚未就绪, 被调用方是否需要拿到数据结果再返回 。 reactor: 通知我有就绪状态了, preactor:通知我数据已经从内核拷贝到了用户空间。 1.同步与异步 同步和异步关注的是 消息通信机制 (synchronous communication/ asynchronous communication) 所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。 换句话说,就是由*调用者*主动等待这个*调用*的结果。 而异步则是相反, *调用*在发出之后 ,这个调用就直接返回了,所以没有返回结果 。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。 典型的异步编程模型比如Node.js 举个通俗的例子: 你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。 而异步通信机制,书店老板直接告诉你我查一下啊

Python 中的协程 (3) 基础概念

戏子无情 提交于 2020-03-25 15:36:58
1 进程和线程 进程 Process:一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式)。 线程 Thread: 线程是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。线程的本质:线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。 进程和线程的区别:进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些

一句话读懂Threadlocal

♀尐吖头ヾ 提交于 2020-03-25 15:13:33
3 月,跳不动了?>>> threadlocal是把ThreadLocal实例作为key,要保持的对象作为值,设置到当前线程的ThreadLocalMap 中。 因此数据是保存在当前线程中的。 ThreadLocalMap实例是作为java.lang.Thread的成员变量存储的,每个线程有唯一的一个threadLocalMap。这个map以ThreadLocal对象为key,”线程局部变量”为值,所以一个线程下可以保存多个”线程局部变量”。对ThreadLocal的操作,实际委托给当前Thread,每个Thread都会有自己独立的ThreadLocalMap实例,存储的仓库是Entry[] table;Entry的key为ThreadLocal,value为存储内容;因此在并发环境下,对ThreadLocal的set或get,不会有任何问题。 总之,ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点: 每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。 将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中

多线程实战2

女生的网名这么多〃 提交于 2020-03-25 11:45:47
3 月,跳不动了?>>> 固定个数的线程池,每个线程处理自己的任务 CountDownLatch countDownLatch = new CountDownLatch(maxThread); 来控制所有任务执行完成。 private static AtomicBoolean RUN_FLAG = new AtomicBoolean(false); private String singleHandler(int pageSize, Integer maxThread) { if (!RUN_FLAG.compareAndSet(false, true)) { log.info("【余额退出】任务进行中,不能再次执行"); return "任务进行中,不能再次执行"; } try { this.handler(pageSize, maxThread); return "处理完成"; } finally { RUN_FLAG.set(false); } } private void handler(int pageSize, Integer maxThread) { if (maxThread == null) { maxThread = 10; } final int maxThreads = maxThread; CountDownLatch countDownLatch =