synchronized 可以修饰几种东西:代码块,变量,静态方法,非静态方法
1.修饰非静态方法
在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();
}
}