【JAVA书单】-《JAVA多线程核心技术》-第三章 线程间通信

7 篇文章 0 订阅

此文是对《JAVA多线程编程核心技术》的一点总结,如果想要了解具体细节可以去看原书。

第三章 线程间通信

使用wait/notify实现线程间的通信

  • 方法wait()的作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法用来将当前线程置入“预执行队列”中,并且在wait()所在的代码行处停止执行,直到接到通知或中断为止。在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。执行wait()方法后,当前线程释放锁
  • 如果调用wait()时没有持有适当的锁,则抛出IllegalMonitorStateException,它是RuntimeException的一个子类,因此,不需要try-catch语句捕获异常。
  • 方法notify()也要在同步方法或同步代码块中调用,即在调用前,线程也必须获得该对象的对象级别锁。
  • notify()用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选出一个呈wait状态的线程,对其发出通知notify,并使它等待获取该对象的对象锁
  • 在执行notify()方法后,不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,当前线程才会释放锁。

线程状态

在这里插入图片描述

  • 生产者/消费者模式的实现

创建存储值的对象

public class MyStack {
    private List list = new ArrayList<>();

   synchronized public void push() {
        try{
            while (list.size() == 1) {
                this.wait();
            }
            list.add("anyString=" + Math.random());
            this.notify();
            System.out.println("push=" + list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized public String pop() {
       String returnValue = "";
       try {
           while (list.size() == 0) {
               System.out.println("pop操作中的:" + Thread.currentThread().getName() + " 线程呈wait状态");
               this.wait();
           }
           returnValue = "" + list.get(0);
           list.remove(0);
           this.notify();
           System.out.println("pop=" + list.size());
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       return returnValue;
    }
}

生产者

/**
 * 生产者
 */
public class P {
    private MyStack myStack;

    public P(MyStack myStack) {
        this.myStack = myStack;
    }


    public void pushService() {
      myStack.push();
    }
}

生产者线程

public class P_Thread extends Thread {
    private P p;

    public P_Thread(P p) {
        this.p = p;
    }

    @Override
    public void run() {
        while (true) {
            p.pushService();
        }
    }
}

消费者

/**
 * 消费者
 */
public class C {
    private MyStack myStack;

    public C(MyStack myStack) {
        this.myStack = myStack;
    }

    public void popService() {
        System.out.println("pop=" + myStack.pop());
    }
}

消费者线程

public class C_Thread extends Thread {
    private C r;

    public C_Thread(C r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true) {
            r.popService();
        }
    }
}

启动类

public class Run {
    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        P p1 = new P(myStack);
        P p2 = new P(myStack);
        P p3 = new P(myStack);
        P_Thread pThread1 = new P_Thread(p1);
        P_Thread pThread2 = new P_Thread(p2);
        P_Thread pThread3 = new P_Thread(p3);
        pThread1.start();
        pThread2.start();
        pThread3.start();
        C r1 = new C(myStack);
        C r2 = new C(myStack);
        C r3 = new C(myStack);
        C_Thread cThread1 = new C_Thread(r1);
        C_Thread cThread2 = new C_Thread(r2);
        C_Thread cThread3 = new C_Thread(r3);
        cThread1.start();
        cThread2.start();
        cThread3.start();
    }
}
  • 方法join的使用
    方法join的作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程销毁后再执行线程z后面的代码。
  • ThreadLocal类的使用
    ThreadLocal类主要解决的是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值