public class Tickets implements Runnable{ private int ticket = 100; public void run(){ while(true){ if(ticket > 0){ System.out.println(Thread.currentThread().getName() + "出售票" + ticket--); } } } } pubilc static void main(String[] args){ Tickets ts = new Ticket(); Thread t0 = new Thread(ts); Thread t1 = new Thread(ts); Thread t2 = new Thread(ts); t0.start(); t1.start(); t2.start(); }
同步代碼塊解決線程問題:synchronized(Object obj){線程要操做的代碼塊}
java
private Object obj = new Object(); public void run(){ while(true){ synchronized(obj){ if(ticket > 0){ System.out.println(Thread.currentThread().getName() + "出售票" + ticket--); } } } }
同步對象:
任意對象,對象監聽器多線程
沒有鎖的線程不能執行只能等待,碰見同步代碼塊,併發
private int ticket = 100; public void run(){ while(true){ pay(); } } } public static synchronized void pay(){ if(ticket > 0){] System.out.println(Thread.currentThread().getName() + "出售票" + ticket--); } //在同步方法中,對象鎖是this。可是在靜態方法中,對象鎖不是this,this屬於對象,優先於static,是本類本身.class
在線程中,只有出了同步代碼塊纔會釋放對象鎖,可是要是出現了異常就不會釋放了。因此在jdk5之後就使用Lock接口
this
public void lock() public void unlock()
鎖的嵌套
出現了互鎖線程
public class lockA{ public static final LockA lockA = new LockA(); private LockA(){ } } public class lockB{ public static final LockB lockB = new LockB(); private LockB(){ } } public class DeadLock implements Runnable{ private int i = 0; public void run(){ while(ture){ if(i%2 == 0){ //先進入A同步,在進入B同步 synchronized(LockA.locka){ System.out.println("if...locka"); synchronized(LockB.lockb){ System.out.println("else...lockb"); } } }else{ synchronized(LockB.lockb){ System.out.println("if...lockb"); synchronized(LockA.locka){ System.out.println("else...locka"); } } } } } }
多個線程操做同一個數據,可是操做的動做可能並不相同,經過必定的手段將各個線程有效的利用,既--等待喚醒機制code
public void wait()釋放正在執行的線程的執行權,放到存儲池對象
public void notify()喚醒在線程池中wait()的線程,一次喚醒一個,並且是任意的。接口
public void notifyAll(),喚醒在線程池中全部的wait()線程喚醒get
[x] 線程之間是否是全部的數據都鎖上了同步
[x] 是否是用的同一個鎖
public class Resource{ public String name; public String sex; public boolean flag;//喚醒標識 public Resource(String name,String sex){ this.name = name; } } public class InputThread implements Runnable{ private Resource r = null; public InputThread(Resource r){ this.r = r; } public void run(){ int i = 0; while(true){ synchronized(r){ if(r.flag){ try{ //必須是鎖對象調用 r.wait(); }catch(Exception ex){ System.out.println(ex.getMessage()); } } if(i%2 == 0){ r.name = "張三"; r.sex = "男"; }else{ r.name = "lisi"; r.sex = "nv"; } i++; //執行完成,將標識修改,並喚醒對方。 r.flag = true; r.notify(); } } } } public class OutputThread{ private Resource r = null; public void run(){ //使用同一個對象鎖 synchronized(r){ while(true){ if(r.flag){ try{ //必須是鎖對象調用 r.wait(); }catch(Exception ex){ System.out.println(ex.getMessage()); } System.out.println(r.name); //執行完成,將標識修改,並喚醒對方。 r.flag = false; r.notify(); } } } public OutputThread(Resource r){ this.r = r; } } public class ThreadDemo{ public static void main(String[] args){ Resource r = new Resource(); InputThread int = new InputThread(r); OutputThread outt = new OutputThread(r); Thread in = new Thread(in); Thread out = new Thread(out); } }
對於線程來講,要同步必須操做同一個鎖對象
才能夠,若是是使用各自來作本身的線程喚醒對象就不能實現同一個鎖對象
,而且對於實現類來講,調用者是誰?
==全部的線程的等待喚醒必須是鎖對象調用,調用者是誰?任何方法都須要被調用,本類線程類是沒有wait方法的,只有調用父類的super(),可是父類也沒有這個方法,調用這個的鎖對象是誰就由誰來調用,因此,同步的等待喚醒方法都是Object類的方法==