线程之间的通信


接着上一篇继续看,这篇主要讲线程之间的通信,如果没看之前的请点击多线程详解,线程的同步,先看几个方法:

  • wait()与notify()和notifyAll()
    • wait():当前线程挂起并放弃CPU、同步资源,让别的线程可以访问并修改共享资源,而当前线程排队等候再次对资源访问。
    • notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待。
    • notifyAll():唤醒正在排队等待资源的所有线程结束等待。
  • Java.lang.Object提供的这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报java.lang.IllegalMonitorStateException异常。

方法的运用,2个线程交互打印到100

class SubThread implements Runnable{
  int number=1; 
  public void run(){
  while (true){
  synchronized(this){
  notify();//当线程挂起的时候,需要唤醒
   if(number<=100){
      try{
      Thread.currentThread().sleep(1000);
      }catch (Exception e){
      }
       System.out.print(number);
       number++;
      }else{
      break;
      }
      try{
      wait();
      }catch (Exception e){
      }
  }
  }
  }
}
 class TestThread{
  public static void main(String []args){
  SubThread st=new SubThread();
  Thread th1=new Thread(st);
  Thread th2=new Thread(st);
  th1.setName("甲");
  th2.setName("乙");
  th1.start();
  th2.start();
 }
 }

经典例题,消费者与生产者

生产者(productor)将产品交给店员(clerk),而消费者(Customer)从店员取走,店员一次只有有固定数量的产品20个,如果生产者生产大于20个,店员会叫生产者停一下,如果店里有空位放产品再通知生产者生产,如果店中没产品,店员会告诉消费者等一下,有产品再叫消费者来取走产品。

分析例题:

  1. 是否涉及多线程问题?是,消费者和生产者。
  2. 是否涉及到共享数据?有,产品的固定数量。
  3. 是否涉及到线程的通信? 是,消费者和生产者之间通信。
class Clerk{
        int number;
        public synchronized void addProduct(){//锁为this,Clerk对象
            if(number>=20){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                number++;
                notifyAll();
            }
        }
        public synchronized void cutProduct(){//锁为this,Clerk对象
            if(number<=0){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                number--;
                notifyAll();
            }
        }
    }
    //生产者
    class Productor implements Runnable{
        Clerk clerk;
        public   Productor (Clerk clerk){
            this.clerk=clerk;
        }
        @Override
        public void run() {
            System.out.print("生产者生产产品");
            while (true){
                try {
                    Thread.currentThread().sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                clerk.addProduct();
            }
        }
    }
    //消费者
    class Customer implements Runnable{
        Clerk clerk;
        public   Customer (Clerk clerk){
            this.clerk=clerk;
        }
        @Override
        public void run() {
            System.out.print("消费者消费产品");
            while (true){
                try {
                    Thread.currentThread().sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                clerk.cutProduct();
            }
        }
    }
    class TestThread{
        public static void  main(String [] agrs){
            Clerk clerk=new Clerk();
            Productor pc=new Productor(clerk);
            Customer cm=new Customer(clerk);
            Thread t1=new Thread(pc); //生产者线程
            Thread t3=new Thread(pc);//生产者线程
            Thread t2=new Thread(cm);//消费者线程
            t1.setName("生产者");
            t3.setName("生产者2");
            t2.setName("消费者");
            t1.start();
            t2.start();
            t3.start();
        }
    }

常见疑难解答:

  1. java中线程与线程之间怎么通信。

    不同线程共享一个变量,并对该变量的访问进行同步操作,因为他们共享一个内存空间,所以相比之下,它比进程之间要简单。

  2. 什么是进程的死锁和饥饿。

    饥饿:当一个进程永久性的占有资源,使得其他进程得不到该资源,就发生了饥饿。死锁:当2个线程都需要对方的资源时,但因为某种原因都得不到资源,就僵持不下,这样就出现了死锁。

  3. 多线程的死锁问题。

    避免使用suspend()和resume()方法,这些方法与生俱来就产生死锁的缺点。不要对长时间I/O操作的方法施加锁。 使用多个锁是,确保所有线程都按相同的顺序获得锁。

可供参考的文档

  1. 多线程死锁的产生以及如何避免死锁
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值