Java:线程通信

所谓线程通信,通俗的来说,就是多个线程之间需要进行信息交换,达到改变线程执行顺序、状态的目的。


1:三种方法

  • wait():一旦执行该方法,当前进程就进入阻塞状态,并释放同步监视器(与sleep不同的一点)。

  • notify():唤醒被wait的线程中优先级最高者。(唤醒一个)

  • notifyAll ():唤醒被wait的所有线程。(唤醒所有)

这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报java.lang.IllegalMonitorStateException异常

这三个方法的调用者必须是同步代码块或同步方法中的同步监视器

因为这三个方法必须有锁对象调用,而任意对象都可以作为synchronized的同步锁,因此这三个方法只能在Object类中声明。

在这里插入图片描述


2:代码实例:


使用两个线程打印 1-100,线程1, 线程2 交替打印
class Number implements Runnable{
    
    
    private int number = 1;
    Object obj = new Object();
    @Override
    public void run() {
    
    
        while(true){
    
    
            synchronized(obj){
    
    
                obj.notify();//notify()方法唤醒线程,notifyAll()唤醒所有线程
                if(number <= 10){
    
    
                    System.out.println(Thread.currentThread().getName()+"打印了:"+number);
                    number++;
                    try {
    
    
                        obj.wait();//wait()方法将线程阻塞,同时释放该线程的锁
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }else {
    
    
                    break;
                }
            }
        }
    }
}

public class ConmmunicationTest {
    
    
    public static void main(String[] args) {
    
    
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);
        t1.start();
        t2.start();
    }
}

3:生产者消费者问题

class Clerk{
    
    
    private int num;//产品数量
    //生产产品
    public synchronized void produceProduct() {
    
    
        if(num < 20){
    
    
            num++;
            System.out.println(Thread.currentThread().getName() + ":开始生产第" + num + "个产品");
            notify();//生产者
        }else{
    
    
            //当产品数量大于20时,生产者阻塞
            try {
    
    
                wait();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }

    }
    //消费产品
    public synchronized void consumeProduct() {
    
    
        if(num>0){
    
    
            System.out.println(Thread.currentThread().getName() + ":开始消费第" + num + "个产品");
            num--;
            notify();//消费者消费完产品后唤醒生产者
        }else{
    
    
            //没有产品时,消费者阻塞
            try {
    
    
                wait();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

//生产者类
class Producer extends Thread{
    
    
    private Clerk clerk;
    public Producer(Clerk clerk){
    
    
        this.clerk = clerk;
    }
    @Override
    public void run() {
    
    
        //生产产品
        while(true){
    
    
            clerk.produceProduct();
        }
    }
}

class Consumer extends Thread{
    
    
    private Clerk clerk;
    public Consumer(Clerk clerk){
    
    
        this.clerk = clerk;
    }
    @Override
    public void run() {
    
    
        //消费者消费产品
        while(true){
    
    
            clerk.consumeProduct();
        }
    }
}

public class ProductTest {
    
    
    public static void main(String[] args){
    
    
        Clerk clerk = new Clerk();
        Producer p = new Producer(clerk);
        Consumer c = new Consumer(clerk);
        p.setName("生产者");
        c.setName("消费者");
        p.start();
        c.start();
    }
}

4:wait 和 sleep 方法的异同

  • 相同点:
    (1)一旦执行方法,都可以使得当前的线程进入阻塞状态。-
  • 不同点:
    (1)两个方法声明的位置不同:Thread类中声明sleep(),Object类中声明wait()。
    (2)调用的要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用在同步代码块或同步方法中。
    (3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放同步监视器,而wait()会释放同步监视器

猜你喜欢

转载自blog.csdn.net/m0_51755061/article/details/115093603