对象锁,锁的是类的对象实例。java
类锁 ,锁的是每一个类的的Class对象,每一个类的的Class对象在一个虚拟机中只有一个,因此类锁也只有一个。express
适合于只有一个线程写,多个线程读的场景,由于它只能确保可见性。ide
线程变量。能够理解为是个map,类型 Map<Thread,Integer>this
难以保证及时性,资源开销很大,spa
wait() 对象上的方法,将是当前执行线程进行等待。线程
notify/notifyAll 对象上的方法 发送信号量,唤醒线程。code
代码示例:对象
/** * @Auther: BlackKingW * @Date: 2019/4/14 12:09 * @Description: */ public class Express { public final static String CITY = "ShangHai"; private int km;/*快递运输里程数*/ private String site;/*快递到达地点*/ public Express() { } public Express(int km, String site) { this.km = km; this.site = site; } /* 变化千米数,而后通知处于wait状态并须要处理千米数的线程进行业务处理*/ public synchronized void changeKm(){ this.km = 101; notifyAll(); //其余的业务代码 } /* 变化地点,而后通知处于wait状态并须要处理地点的线程进行业务处理*/ public synchronized void changeSite(){ this.site = "BeiJing"; notify(); } public synchronized void waitKm(){ while(this.km<=100) { try { wait(); System.out.println("check km thread["+Thread.currentThread().getId() +"] is be notifed."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("the km is"+this.km+",I will change db."); } public synchronized void waitSite(){ while(CITY.equals(this.site)) { try { wait(); System.out.println("check site thread["+Thread.currentThread().getId() +"] is be notifed."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("the site is"+this.site+",I will call user."); } } /** * @Auther: BlackKingW * @Date: 2019/4/14 12:09 * @Description: */ public class TestWN { private static Express express = new Express(0,Express.CITY); /*检查里程数变化的线程,不知足条件,线程一直等待*/ private static class CheckKm extends Thread{ @Override public void run() { express.waitKm(); } } /*检查地点变化的线程,不知足条件,线程一直等待*/ private static class CheckSite extends Thread{ @Override public void run() { express.waitSite(); } } public static void main(String[] args) throws InterruptedException { for(int i=0;i<3;i++){//三个线程 new CheckSite().start(); } for(int i=0;i<3;i++){//里程数的变化 new CheckKm().start(); } Thread.sleep(1000); express.changeKm();//快递地点变化 } }
等待和通知的标准范式ip
等待方:资源
通知方来讲
notify和notifyAll应该用谁?
应该尽可能使用notifyAll,使用notify由于有可能发生信号丢失的的状况
thread.Join把指定的线程加入到当前线程,能够将两个交替执行的线程合并为顺序执行的线程。
好比在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
代码示例:
/** * @Auther: BlackKingW * @Date: 2019/4/14 12:09 * @Description: */ public class UseJoin { // static class JumpQueue implements Runnable { private Thread thread;//用来插队的线程 public JumpQueue(Thread thread) { this.thread = thread; } public void run() { try { System.out.println(thread.getName()+" will be join before " +Thread.currentThread().getName()); thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" terminted."); } } public static void main(String[] args) throws Exception { Thread previous = Thread.currentThread();//如今是主线程 for (int i = 0; i < 10; i++) { //i=0,previous 是主线程,i=1;previous是i=0这个线程 Thread thread = new Thread(new JumpQueue(previous), String.valueOf(i)); System.out.println(previous.getName()+" jump a queue the thread:" +thread.getName()); thread.start(); previous = thread; } SleepTools.second(2);//让主线程休眠2秒 System.out.println(Thread.currentThread().getName() + " terminate."); } }
线程在执行yield()之后,持有的锁是不释放的
sleep()方法被调用之后,持有的锁是不释放的
调动方法以前,必需要持有锁。调用了wait()方法之后,锁就会被释放,当wait方法返回的时候,线程会从新持有锁
调动方法以前,必需要持有锁,调用notify()方法自己不会释放锁的