Java线程同步与通信(生产者消费者问题)

1.同步代码块

synchronized(Object o){
	//同步代码
}
public class WindowTest2 {
    public static void main(String[] args) {
        new Window2("窗口1").start();
        new Window2("窗口2").start();
        new Window2("窗口3").start();
    }
}

class Window2 extends Thread{

    private static int ticket=100;
    private static Object obj = new Object();    //同步锁对象,注意这里必须让同步锁对象唯一,使用static修饰

    public Window2(String str){
        super(str);
    }
    @Override
    public void run() {
        while (true){
            synchronized(obj){   //也可以使用Window2.class,反射机制
                if (ticket>0){
                    System.out.println(Thread.currentThread().getName()+"售出:"+ticket);
                    ticket--;
                }else {
                    break;
                }
            }
        }
    }
}

当使用实现Runnable接口的时候也可以用this来充当同步锁对象
2.同步方法
实现Runnable接口的方式中,同步方法的同步锁对象为this

public static synchronized void(){} 
public class WindowTest3 {
    public static void main(String[] args) {
        Window3 Window3 = new Window3();

        Thread t1 = new Thread(Window3, "窗口1");
        Thread t2 = new Thread(Window3, "窗口2");
        Thread t3 = new Thread(Window3, "窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

class Window3 implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        while (true){
            show();
        }
    }

    private synchronized void show(){
        if(ticket>0){
            System.out.println(Thread.currentThread().getName()+"售"+ticket--);
        }
    }
}

使用继承Thread类时:
如果同步方法不定义成静态的同步方法时,默认同步锁对象为this,这样的话达不到同步的作用,因为同步锁对象不唯一
应该将同步方法定义成静态的同步方法,此时的同步锁对象则为 当前类名.class 这样才能达到同步的效果

public class WindowTest4 {
    public static void main(String[] args) {
        new Window4("窗口1").start();
        new Window4("窗口2").start();
        new Window4("窗口3").start();
    }
}

class Window4 extends Thread{

    private static int ticket=100;

    public Window4(String str){
        super(str);
    }
    @Override
    public void run() {
        while (true){
            show();
        }
    }

    private static synchronized void show(){     //静态同步方法的同步锁对象为当前类,即.class,非静态方法的同步锁对象则为this
        if(ticket>0){
            System.out.println(Thread.currentThread().getName()+"售"+ticket--);
        }
    }
}

3.Lock锁

public class LockTest  {
    public static void main(String[] args) {
        Test test  = new Test();
        new Thread(test).start();
        new Thread(test).start();
        new Thread(test).start();
    }
}

class Test implements Runnable{
    private int ticket = 100;
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true){
            lock.lock();  //加锁
            if (ticket>0){
                System.out.println(Thread.currentThread().getName()+"售:"+ticket+" 张票");
                ticket--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                break;
            }
            lock.unlock();  //一般放在finally中,释放锁
        }
    }
}

4.线程通信
主要方法wait(),notify(),notifyAll()这几个方法必须在同步代码块或同步方法中使用
生产者消费者问题:

//生产者
public class Productor extends Thread {

    private Count count;

    public Productor(Count count, String name) {
        super(name);
        this.count = count;
    }

    @Override
    public void run() {
        while (true) {
            count.ProductProduction();
        }
    }
}

//消费者
public class Consumer extends Thread {

    private Count count;

    public Consumer(Count count, String name) {
        super(name);
        this.count = count;
    }

    @Override
    public void run() {
        while (true) {
            count.ConsumeProduction();
        }
    }
}

//共享资源
public class Count {
    private int count=0;

    //同步方法
    public synchronized void ProductProduction(){
            if (count<20){
                count++;
                System.out.println(Thread.currentThread().getName()+"生产第"+ count + "件产品");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                notify();    //当有产品时,告知消费者可以进行消费,唤醒消费者线程
            }else {
                try {
                    wait();   //当产品数为20,已满的时候则不能在进行生产,进入阻塞状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    }

    public synchronized void ConsumeProduction(){
            if(count<=0){
                try {
                    wait();      //产品数为0时,消费进程进入阻塞状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                System.out.println(Thread.currentThread().getName()+"消费第"+ count + "件产品");
                count--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                notify();    //唤醒已阻塞的线程
            }
    }
}

public class Demo {
    public static void main(String[] args) {
        Count count = new Count();
        Productor productor = new Productor(count, "甲");
        Consumer consumer = new Consumer(count, "乙");

        productor.start();
        consumer.start();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值