多线程补充内容——Java面向对象基础(28)

一、一个经典的问题——生产者,消费者问题

1.需要明确的是,只有当生产者生产出产品后,消费者才能消费。

2.只有当消费者消费了产品后,生产者才能再生产。

3.即产品为资源

4.采用信号灯的机制处理,产品设为引号灯。

/**
 * 生产者与消费者关系:
 *     信号灯:T F
 *     当信号灯T: 生产者生产,生产完消费者再消费。
 *     当信号灯F: 消费者消费,消费完生产者再生产。
 *         
 *
 */
public class Product {
    private String productName;
    private boolean flag = true; //信号灯
    
    public synchronized void produce(String productName){
        if(!flag){
            try {
                this.wait();//如果当前产品还没有被消费掉,就将生产阻塞。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            try {
                Thread.sleep(2000);//模拟网络延迟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.productName=productName;
            System.out.println("生产者生产:"+productName);
            this.notify();//通知另外一个线程,唤醒
            flag=false;//改变信号灯,表示当前有产品
        
    }
    
    public synchronized void consume(){
        if(flag){
            try {
                this.wait();//如果当前没有产品,则不能消费,就将消费阻塞
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            try {
                Thread.sleep(2000);//模拟网络延迟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("消费者消费:"+productName);
            this.notify();//通知另外一个线程,唤醒
            flag=true;//改变信号灯,表示当前产品被消耗掉,没有了
        
    }

}
public class Consumer implements Runnable{
    private Product product;
    public Consumer(Product product){
        this.product=product;
    }
    @Override
    public void run() {
        for(int i = 0; i < 20; i++){
            if(i % 2 == 0){
                product.produce("产品1");
            }else{
                product.produce("产品2");
            }
        }
        
    }
    
}
public class Producer implements Runnable{
    private Product product;
    public Producer(Product product){
        this.product=product;
    }
    @Override
    public void run() {
        for(int i = 0; i < 20; i++){
            product.consume();
        }
    }
    
}
public class MyMain {

    public static void main(String[] args) {
        Product product=new Product();
        Producer producer=new Producer(product);
        Consumer consumer=new Consumer(product);
        Thread th01=new Thread(producer);
        Thread th02=new Thread(consumer);
        th01.start();
        th02.start();
        
    }

}

二、关于synchronized()中的参数

   

参数  相同点  不同点
参数是this对象 都能实现同步 实现同步的同时,会阻塞其他线程获取这个对象的锁,影响执行效率
参数是非this对象  都能实现同步  synchronized(非this)代码块中程序与同步方法是异步的,不与其他锁this同步方法争夺this锁,可以提高执行效率

对象锁,sychronized(object),如果再有其他线程要访问这段代码,由于Object已经被锁住,要等到synchronized里面的方法运行完成以后,才可以访问这段代码。

给对象加锁(可以理解为给这个对象的内存上锁,注意 只是这块内存,其他同类对象都会有各自的内存锁),这时候在其他一个以上线程中执行该对象的这个同步方法(注意:是该对象)就会产生互斥