此外,在 runnable 状态的线程是处于被调度的线程,此时的调度顺序是不一定的 。Thread 类中的 yield 方法可以让一个 running 状态的线程转入 runnable 。
内功心法:每个对象都有的方法(机制)
synchronized, wait, notify 是任何对象都具有的同步工具 。让我们先来了解他们

文章插图
monitor
他们是应用于同步问题的人工线程调度工具 。讲其本质,首先就要明确 monitor 的概念,Java 中的每个对象都有一个监视器,来监测并发代码的重入 。在非多线程编码时该监视器不发挥作用,反之如果在 synchronized 范围内,监视器发挥作用 。
wait/notify 必须存在于 synchronized 块中 。并且,这三个关键字针对的是同一个监视器(某对象的监视器) 。这意味着 wait之后,其他线程可以进入同步块执行 。
当某代码并不持有监视器的使用权时(如图中5的状态,即脱离同步块)去 wait 或 notify,会抛出java.lang.IllegalMonitorStateException 。
也包括在 synchronized 块中去调用另一个对象的 wait/notify,因为不同对象的监视器不同,同样会抛出此异常 。
再讲用法:
- synchronized 单独使用:
- 代码块:如下,在多线程环境下,synchronized 块中的方法获取了 lock 实例的 monitor,如果实例相同,那么只有一个线程能执行该块内容
public class Thread1 implements Runnable { Object lock; public void run { synchronized(lock){ ..do something } } }- 直接用于方法:相当于上面代码中用 lock 来锁定的效果,实际获取的是 Thread1 类的 monitor 。更进一步,如果修饰的是 static 方法,则锁定该类所有实例
public class Thread1 implements Runnable { public synchronized void run { ..do something }}- synchronized, wait, notify 结合:典型场景生产者消费者问题
/** * 生产者生产出来的产品交给店员 */ public synchronized void produce { if(this.product >= MAX_PRODUCT) { try { wait; System.out.println("产品已满,请稍候再生产"); } catch(InterruptedException e) { e.printStackTrace ; } return; } this.product++; System.out.println("生产者生产第" + this.product + "个产品."); notifyAll; //通知等待区的消费者可以取出产品了 } /** * 消费者从店员取产品 */ public synchronized void consume { if(this.product <= MIN_PRODUCT) { try { wait; System.out.println("缺货,稍候再取"); } catch (InterruptedException e) { e.printStackTrace; } return; } System.out.println("消费者取走了第" + this.product + "个产品."); this.product--; notifyAll; //通知等待去的生产者可以生产产品了 }volatile
多线程的内存模型:main memory(主存)、working memory(线程栈),在处理数据时,线程会把值从主存 load 到本地栈,完成操作后再 save 回去 (volatile 关键词的作用:每次针对该变量的操作都激发一次 load and save)。

文章插图
volatile
针对多线程使用的变量如果不是 volatile 或者 final 修饰的,很有可能产生不可预知的结果(另一个线程修改了这个值,但是之后在某线程看到的是修改之前的值) 。其实道理上讲同一实例的同一属性本身只有一个副本 。但是多线程是会缓存值的,本质上,volatile 就是不去缓存,直接取值 。在线程安全的情况下加 volatile 会牺牲性能 。
太祖长拳:基本线程类
基本线程类指的是 Thread 类,Runnable 接口,Callable 接口
Thread 类实现了 Runnable 接口,启动一个线程的方法:
MyThread my = new MyThread; my.start;Thread类相关方法
//当前线程可转让 cpu 控制权,让别的就绪状态线程运行(切换)
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Java源码中>>,>>>的区别是啥?我给你彻底讲清
- Java基础 字节流、字符流
- MySQL如何存储时间datetime还是timestamp
- Java并发的原子性、可见性、有序性
- 数据结构Java实现:循环链表和双向链表
- Javascript创建对象方式总结
- 炖鸡放啤酒还能加水吗
- 干油豆皮用热水还是冷水泡
- 考研|考研差1分进复试,选择“二战”还是“找工作”?学姐的话很中肯
- 抖音是开通橱窗还是开通抖音小店 抖音小店和橱窗哪个好
