![](https://img-blog.csdnimg.cn/20201014180756922.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程
一只可爱的小狐狸
我亦无他,惟手熟尔
展开
-
JAVA锁机制
1.乐观锁乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。2.悲观锁悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次原创 2021-07-25 21:18:18 · 720 阅读 · 3 评论 -
Condition接口
Condition接口Condition是j.u.c包下提供的一个接口。可以翻译成 条件对象,其作用是线程先等待,当外部满足某一条件时,在通过条件对象唤醒等待的线程。void await() throws InterruptedException;让线程进入等待,如果其他线程调用同一Condition对象的notify/notifyAll,那么等待的线程可能被唤醒。释放掉锁void signal();唤醒等待的线程void signalAll();唤醒所有线程练习题:写2个线程,其中一个打印1-原创 2021-02-22 15:35:54 · 1215 阅读 · 8 评论 -
Lock的使用
Lock的使用Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制。本质上Lock仅仅是一个接口,可以通过显式定义同步锁对象来实现同步,能够提供比synchronized更广泛的锁定操作,并支持多个相关的Condition对象void lock();尝试获取锁,获取成功则返回,否则阻塞当前线程void lockInterruptibly() throws InterruptedException;尝试获取锁,线程在成功获取锁之前被中断,则放弃获取锁,抛出异常boole原创 2021-02-22 09:22:22 · 1220 阅读 · 3 评论 -
生产者/消费者模式
生产者/消费者模式生产/消费者问题是个非常典型的多线程问题,涉及到的对象包括生产者、消费者、仓库和产品他们之间的关系如下:生产者仅仅在仓储未满时候生产,仓满则停止生产。消费者仅仅在仓储有产品时候才能消费,仓空则等待。当消费者发现仓库没产品可消费时候会通知生产者生产。生产者在生产出可消费产品时候,应该通知等待的消费者去消费。生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。pub原创 2021-02-22 09:21:09 · 1369 阅读 · 0 评论 -
同步方法块
同步方法块上面的两种方式比较死板,普通方法同步是以当前对象作为锁,静态方法同步是以当前类对象作为锁所以引入更为灵活的方式:同步块,将锁对象作为参数进行传递synchronized(account){}同步监视器可以阻止多个线程对同一个共享资源的并发访问,任何时刻只有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放堆该同步监视器的锁定。...原创 2021-02-20 09:26:46 · 1253 阅读 · 0 评论 -
同步静态方法
同步静态方法修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁同步监视器是当前类对象Class c=Date.classpublic class App { private static int num = 0; public static synchronized void add() { System.out.println(Thread.currentThread().getName()+":begin...."+new Date()); int cc = nu原创 2021-02-20 09:25:38 · 1231 阅读 · 2 评论 -
同步实例方法
同步实例方法修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁方法上添加synchronized就叫做同步方法,例如public synchronized void draw(double amount){}注意:在一个类对象中所有的同步方法是互斥的只要有一个线程进行了当前类对象(只能一个对象)的同步方法,则不允许其它线程在进入当前这个对象的任何同步方法,但是允许进入非同步方法同样当前线程则可以进入当前类对象的其它同步方法,也允许进入非同步方法,当线程进入同步方法,则获取同步锁,原创 2021-02-20 09:24:30 · 1244 阅读 · 3 评论 -
银行取钱操作
银行取钱操作定义账户类—临界资源定义取钱线程public class 取钱线程 extends Thread { private 账户类 account;//取钱的账户 private double amount;//取钱的金额 public 取钱线程(账户类 account,double amount) { this.account=account; this.amount=amount; } @Override public void run() { //首先判断余额是否满原创 2021-02-20 09:23:23 · 1197 阅读 · 2 评论 -
同步处理
同步处理的引入在java语言中存在两种内建的synchronized语法:synchronized代码块和synchronized方法( 静态方法和非静态方法)可以解决线程安全问题首先synchronized将并行改为串行,当然会影响程序的执行效率,执行速度会受到影响。其次synchronized操作线程的堵塞,也就是由操作系统控制CPU的内核进行上下文的切换,这个切换本身也是耗时的。所以使用synchronized关键字会降低程序的运行效率。问题线程安全是并发编程中的重要关注点,应该注意到的是,造原创 2021-02-20 09:20:25 · 1298 阅读 · 0 评论 -
理解synchronized的含义
理解synchronized的含义1、synchronized就是给当前的NumOps类型的对象添加了一个互斥锁机制:锁只能有一个2、当有一个线程正在某个同步方法中执行,则其它线程不能进入该对象的任何同步方法中,可以进入非同步方法常见的4种Java线程锁:原子量AtomicInteger、信号量Semaphone、同步处理synchronized和重入锁ReentrantLockjdk6之前是重量级锁,JDK6开始优化为锁的状态总共有四种,无锁状态(没有synchronized)、偏向锁、轻量级锁和原创 2021-02-14 09:57:54 · 2224 阅读 · 3 评论 -
线程的同步问题
线程的同步问题多线程编程中容易出现错误情况,这是由系统的线程调度具有一定随机性造成的,这些情况必须杜绝。- 线程的执行顺序不可重现,但是执行结果一定可重现- 解决方案就是同步处理同步的处理方法当存在多个线程操作共享数据时,需要保证同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再进行,这种方式有个名称叫互斥锁,即能达到互斥访问目的的锁,也就是说当一个共享数据被当前正在访问的线程加上互斥锁后,在同一个时刻,其他线程只能处于等待的状态,直到当前线程处理完毕释放该锁。具体编程原创 2021-02-14 09:57:12 · 1195 阅读 · 0 评论 -
线程的优先级
线程的优先级Java采用的是抢占式的调度机制,提供一个线程调度器来监控程序中启动后进入就绪态的所有线程。线程调度器会按照线程的优先级决定应调度哪个线程来执行线程的优先级用数字表示,范围从1到10,默认值5。但是需要注意的是优先级的具体实现需要依赖于操作系统,所以Java中优先级需要映射到操作系统上,所以可能会出现操作系统中支持的优先级数量少,Java中多个优先级映射到同一个操作系统优先级上。所以在具体使用中建议优先级的差值应该比较大,建议使用预定义的常量t2.setPriority(Thread.MA原创 2021-02-14 09:56:16 · 1175 阅读 · 0 评论 -
调度机制
调度机制具体的调度实现分为操作系统和JVM操作系统的调度机制有多种,一般常见的有2种:时间片Unix和抢占式windows所有的Java虚拟机都有一个线程调度器,用来确定那个时刻运行那个线程。主要有两种调度模型:分时调度模型和抢占式调度模型基于时间片轮转法的抢占式调度。线程调度器会给高优先级有更多的运行机会,如果优先级相同则随机选中,执行时长到达时间片后从新进行调度线程的调度不是跨平台的,它不仅取决于Java虚拟机,还依赖于操作系统。在某些操作系统中,即使运行中的线程没有遇到阻塞,也原创 2021-02-14 09:55:40 · 2144 阅读 · 2 评论 -
volatile
volatile关键字volatile是java提供的一种同步手段,只不过它是轻量级的同步,为什么这么说,因为volatile只能保证多线程的内 存可见性,不能保证多线程的执行原子性。而彻底的同步要保证有序性、可见性和原子性的synchronized任何被volatile修饰的变量,都不拷贝副本到工作内存,任何修改都及时写在主存。因此对于volatile修饰的变量的 修改,所有线程马上就能看到,但是volatile不能保证对变量的修改是原子的volatile存在的意义是,任何线程对a的修改,都会马上被原创 2021-02-13 22:24:24 · 1226 阅读 · 1 评论 -
Java内存模型
Java内存模型Java内存模型定义了一种多线程访问Java内存的规范。Java内存模型将内存分为了主内存和工作内存。类的状态也就是类之间共享的变量,是存储在主内存中的,每 次Java线程用到这些主内存中的变量的时候,会读一次主内存中的变量,并让这些内存在自己的工作内存中有 一份拷贝,运行自己线程代码的时候,用到这些变量,操作的都是自己工作内存中的那一份。在线程代码执 行完毕之后,会将新的值更新到主内存中去定义了几个原子操作,用于操作主内存和工作内存中的变量定义了volatile变量的使用规则h原创 2021-02-13 22:22:59 · 2153 阅读 · 4 评论 -
join方法
join方法主要作用是同步,它可以使得线程之间的并行执行变为串行执行。在A线程中调用了B线程的join()方法时,表示只 有当B线程执行完毕时,A线程才能继续执行。调用这个方法的线程将被阻塞方法join(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)方法具有释放锁的特点。但是 sleep(long)不释放锁。...原创 2021-02-12 21:24:50 · 1187 阅读 · 0 评论 -
sleep方法
sleep方法使得当前线程休眠让当前线程休眠指定时间。休眠时间的准确性依赖于系统时钟和CPU调度机制。如果需要可以通过调用interrupt() 方法来唤醒休眠线程wait(Object中定义的)sleep vs waitJava程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果 等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时 间,但不会释放锁...原创 2021-02-12 21:24:00 · 1638 阅读 · 0 评论 -
线程的状态切换
线程状态切换线程从创建并启动到消亡共经历了5种状态:新建、就绪、运行、阻塞和死亡线程变化的5状态转换:1、新建状态(New):新创建了一个线程对象。new Thread()2、就绪状态(Runnable):线程对象创建后,其它线程调用了该对象的start()方法。只能针对处于新建状态的 线程对象调用start方法,否则IllegalThreadStateException该状态的线程位于可执行线程池中,变得可执行,等待获取CPU的使用权。3、执行状态(Running):就绪状态的线程获取了CP原创 2021-02-11 20:12:32 · 1698 阅读 · 0 评论 -
Executors创建线程池
Executors创建线程池newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无 可回收重用时则新建线程用来创建一个可以无限扩大的线程池,适用于服务器负载较轻,执行很多短期异步任务newFixedThreadPool 创建一个固定大小的定长线程池,可控制线程大并发数,超出的线程会在队列中等 待因为采用无界的阻塞队列,所以实际线程数量永远不会变化,适用于可以预测线程数量的业务中,或者 服务器负载较重,对当前线程数量进行限制ne原创 2021-02-11 20:10:50 · 1147 阅读 · 0 评论 -
ThreadPoolExecutor
ThreadPoolExecutorThreadPoolExecutor是线程池框架的一个核心类,线程池通过线程复用机制,并对线程进行统一管理降低系统资源消耗。通过复用已存在的线程,降低线程创建和销毁造成的消耗;提高响应速度。当有任务到达时,无需等待新线程的创建便能立即执行;提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗大量系统资源,还会降低系统的稳 定性,使用线程池可以进行对线程进行统一的分配、调优和监控。线程池的运行状态总共有5种,其值和含义分别如下:RUNNING:原创 2021-02-10 20:01:01 · 1114 阅读 · 0 评论 -
多线程编程细节
多线程编程细节Thread类Thread类实现了Runnable接口,所以Thread对象也是可运行Runnable对象,同时Thread类也是线程类构造器常见方法:Runnable接口Runnable接口只定义了一个方法public void run(),这个方法要求实现Runnable接口的类实现,Runnable对象称 为可运行对象,一个线程的运行就是执行该对象的run()方法run()方法没有返回值void,而且不能抛出异常Callable接口继承Thread或实现Runnabl原创 2021-02-09 12:52:50 · 1124 阅读 · 0 评论 -
new Thread的弊端
每次new Thread新建对象性能差。线程缺乏统一管理,可能无限制新建线程,相互之间竞争及可能占用过多系统资源导致死机或oom。缺乏更多功能,如定时执行、定期执行、线程中断。OutOfMemoryError即OOM的可能原因?数据库的cursor没有及时关闭未关闭InputStream outputStreamBitmap 使用后未调用recycle()static等关键字非静态内部类持有外部类的引用context泄露流量/数据量峰值:应用程序在设计之初均有用户量和数据量的限制,某一时原创 2021-02-08 12:25:46 · 1862 阅读 · 0 评论 -
线程的编程4种实现方法
1、继承Threadpublic class T4 { public static void main(String[] args) { System.out.println(Thread.currentThread()); Thread t1 = new A1(); t1.start(); }}class A1 extends Thread{ @Override public void run() { for(int i=0;i<10;i++) { System.原创 2021-02-08 12:19:19 · 1335 阅读 · 1 评论 -
多线程和线程
多线程多线程方式是指在一个程序中存在多个线程,每一个线程执行一个独立的任务,多个线程可以并发执行在Java中,一个应用程序可以包含多个线程,每个线程执行特定的任务,并可与其他线程并发执行多线程使系统的空转时间最少,提高CPU利用率,多线程编程环境用方便的模型隐藏CPU在任务间切换的细节吞吐量,充分利用cpu资源,减少CPU空转时间伸缩性,通过CPU核数来提升性能线程的工作场景:1、并发操作,避免阻塞和更有效利用资源。典型的例子有:在长时间工作的程序中使用工作线程避免界面失去响 应。在原创 2021-02-07 19:20:46 · 1245 阅读 · 0 评论 -
进程和线程
进程和线程的关系1、一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(主线程)。2、资源分配给进程,同一进程的所有线程共享该进程的所有资源。3、线程在执行过程中需要协作同步。4、CPU分给线程,即真正在处理机上运行的是线程。5、线程是指进程内的一个执行单元,也是进程内的可调度实体,两者都是动态的概念。线程和进程的区别调度:线程是CPU调度和分配的基本单位,进程是系统资源分配和调度的基本单位。并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行,一个进原创 2021-02-07 19:12:12 · 1279 阅读 · 0 评论 -
进程
进程每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。 (进程是资源分配的最小单位)同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器PC,线程切换开销小。(线程是cpu调度 的最小单位)启动进程的方法线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止启动进程方法1import java.io.BufferedReader;import java.io.InputStreamReader;public class Ma原创 2021-02-05 12:11:02 · 1179 阅读 · 0 评论