在Resource对象内,用synchronized修饰了其中一个方法count。
表示对于对象Resource的一个实例对象resource,当有多个线程引用了这同一个resource时。
这些线程只能有一个线程能进入这个实例resource的count方法中运行。
package com.ylz.dto.dto; public class Resource { private int num = 0; private int min = 0; private int max = 10; public void setNum(int n){ this.num = n; } public int getNum(){ return this.num; } //无论是执行对象的wait、notify还是notifyAll方法,必须保证当前运行的线程取得了该对象的控制权(monitor) @SuppressWarnings("finally") public synchronized void count(String threadNum ,int n){ if(num == min && n < 0){ try { System.out.println("**"+threadNum+"消费数量不足"); wait(); } catch (InterruptedException e) { e.printStackTrace(); }finally { return; } }else if(num == max && n > 0){ try { System.out.println("**"+threadNum+"生产者罢工"); wait(); } catch (InterruptedException e) { e.printStackTrace(); }finally { return; } } num = num + n; if(n > 0){ System.out.println("----"+threadNum+" +1 : 剩余:"+getNum()); }else{ System.out.println("****"+threadNum+" -1 : 剩余:"+getNum()); } notifyAll(); } public void create(String threadNum){ count(threadNum,n); } public void consume(String threadNum){ count(threadNum,n); } }
当,用synchronized修饰了一个以上的方法,create,consume。
表示对于对象Resource的一个实例对象resource,将以这个实例resource为锁,给这个实例resource的两个方法都加上自己为锁。
当有多个线程调用此实例的不同的加了锁的方法时,只有一个方法能运行。
个人理解为,当有一个线程进入某个加锁的方法时,所有加了同一个锁的方法会被同时锁上,所以只有一线程能运行,其它被迫等待,只用当运行中的那个线程运行完毕后
,所有线程再次开始抢着进入,此时只要有一个线程进入任何一个此类方法,所有加了同一个锁的方法将再次锁上,如此循环。
package com.ylz.dto.dto; public class Resource { private int num = 0; private boolean flag = false; public void setNum(int n){ this.num = n; } public int getNum(){ return this.num; } public synchronized void create(String threadNum){ if(flag){ try { System.out.println("**"+threadNum+"生产者罢工"); wait(); return; } catch (InterruptedException e) { } } num ++; System.out.println("----"+threadNum+": 生产者create:"+getNum()); flag = true; notifyAll(); } public synchronized void consume(String threadNum){ if(!flag){ try { System.out.println("**"+threadNum+"消费数量不足"); wait(); return; } catch (InterruptedException e) { } } num --; System.out.println("****"+threadNum+"消费者consume:"+getNum()); flag = false; notifyAll(); } } 下面附上线程和main方法,main方法在provider里面。 package com.ylz.consumer.web.thread; import com.ylz.dto.dto.Resource; public class ConsumerThread implements Runnable{ private String threadNum; private Resource r; public ConsumerThread(Resource r,String threadNum){ this.r = r; this.threadNum = threadNum; } @Override public void run() { // TODO Auto-generated method stub while(true){ try { Thread.sleep(100); r.consume(threadNum); } catch (InterruptedException e) { } } } } package com.ylz.consumer.web.thread; import com.ylz.dto.dto.Resource; public class ProviderThread implements Runnable{ private String threadNum; private Resource r; public ProviderThread(Resource r,String threadNum){ this.r = r; this.threadNum = threadNum; } @Override public void run() { // TODO Auto-generated method stub while(true){ try { Thread.sleep(100); r.create(threadNum); } catch (InterruptedException e) { } } } public static void main(String[] args) { Resource resource = new Resource(); ProviderThread creater1 = new ProviderThread(resource,"P1"); // ProviderThread creater2 = new ProviderThread(resource,"P2"); ConsumerThread consumer1 = new ConsumerThread(resource,"C1"); ConsumerThread consumer2 = new ConsumerThread(resource,"C2"); Thread createrthread1=new Thread(creater1); // Thread createrthread2=new Thread(creater2); Thread consumerthread1=new Thread(consumer1); Thread consumerthread2=new Thread(consumer2); createrthread1.start(); // createrthread2.start(); consumerthread1.start(); consumerthread2.start(); } }