https://www.cnblogs.com/LipeiNet/p/6475851.html
一 synchronized
synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争某个资源的时候会有先后顺序。在java中有三种写synchronized的方式
- 第一种:
- 写在普通方法的前面,这种表示对实例对象加锁。
- 第二种:
- 写在静态方法前面,这种表示对类对象加锁
- 第三种:
- 写在代码块中,锁是Synchonized括号里配置的对象(可能是实例对象,也可能是类对象)
总体说来就2种,一种就是锁实例对象,一种锁类对象。
锁实例对象就是当多个线程同时操作这个实例对象的时候必须先获取锁,如果无法获取锁,则必须处于等待状态,而和锁类对象区别是,当多个线程同时操作的时候,任何以这个类对象实例化的对象都要获取锁才能操作。
二 wait、notify已经notifyAll
wait、notify、notifyAll是Object对象的属性,并不属于线程。我们先解释这三个的一个很重要的概念
wait:使持有该对象的线程把该对象的控制权交出去,然后处于等待状态(这句话很重要,也就是说当调用wait的时候会释放锁并处于等待的状态)
notify:通知某个正在等待这个对象的控制权的线程可以继续运行(这个就是获取锁,使自己的程序开始执行,最后通过notify同样去释放锁,并唤醒正在等待的线程)
notifyAll:会通知所有等待这个对象控制权的线程继续运行(和上面一样,只不过是唤醒所有等待的线程继续执行)
三 一个跑步比赛的线程同步测试
3.1、奔跑者线程
package simm.learning.biztest.threads; import java.util.Date; import java.util.UUID; /** * 奔跑的人 */ public class Runner extends Thread { private FireFlag _flag; private UUID uuid; public Runner(FireFlag flag){ uuid = UUID.randomUUID(); Date dt = new Date(); System.out.println("奔跑者["+uuid.toString()+"]加入队列..."+FireTest.ft.format(dt) +","+dt.getTime()); _flag = flag; } @Override public void run() { _flag.waitForFire(uuid); Date dt = new Date(); System.out.println("奔跑者["+uuid.toString()+"]已出发..."+FireTest.ft.format(dt) +","+dt.getTime()); } }
3.2、开跑信号量
package simm.learning.biztest.threads; import java.util.Date; import java.util.UUID; /** * 开跑标志位 */ public class FireFlag { private volatile boolean fired = false; public synchronized void waitForFire(UUID id){ Date dt = new Date(); System.out.println("奔跑者["+id.toString()+"]准备就绪..."+FireTest.ft.format(dt) +","+dt.getTime()); while (!fired){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void go(){ fired = true; notifyAll(); } }
3.3、比赛现场
package simm.learning.biztest.threads; import java.text.SimpleDateFormat; import java.util.Date; /** * 跑步比赛测试 */ public class FireTest { public static SimpleDateFormat ft = new SimpleDateFormat ("HH:mm:ss.SSS"); public static void main(String[] args) throws InterruptedException { FireFlag flag = new FireFlag(); for(int i=0;i<10;i++){ Thread.sleep(500L); new Runner(flag).start(); } Thread.sleep(3000L); System.out.println("go before-"+ft.format(new Date())); flag.go(); System.out.println("go after-"+ft.format(new Date())); } }
3.4、开跑情况测试结果反馈