java 多线程如何通信_Java多线程系列之:线程间的通信

一,线程间的协作,如何来实现?

1,轮询:难以保证及时性,资源开销很大

2,等待和通知

等待和通知的标准范式:

等待方:

要去获取对象的锁,

然后在循环里判断条件是否满足,不满足调用wait方法。

条件满足,执行业务逻辑

通知方:

获取对象的锁

改变条件

通知所有等待在对象的线程

3,方法:

wait():等待着获取对象的锁

wait(1000):等待超时,超过一定时间就不等待了。

notify:通知一个线程

notifyAll:通知所有等待同一把锁的线程

二,join()方法

1,面试问题:有线程A和线程B,如何保证线程B一定在线程A执行完以后才执行?

方法一:join()

方法二:countDownLatch

解释:如果线程A执行了线程B的join方法,线程A必须等待线程B执行完了以后,线程A才能继续自己的工作。

示例代码:掉用join()方法,可以让该线程优先执行

/**

* 演示join()方法*/

public classUseJoin2 {static classJumpQueue extends Thread{

@Overridepublic voidrun() {for (int i = 0; i <5 ; i++) {

System.out.println("当前线程正在执行步骤"+i);try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}public static voidmain(String[] args) {

System.out.println("进入main方法------>");

JumpQueue jumpQueue= newJumpQueue();

jumpQueue.setName("joinThread");

jumpQueue.start();//jumpQueue.join()方法:会让jumpQueue线程在main线程之前执行

try{

jumpQueue.join();

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("main线程开始处理业务逻辑");try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("main线程处理完业务逻辑了");

}

}

三,yield(),sleep(),wait(),notify()等方法对锁的影响

线程在执行yield()以后,持有的锁是不释放的

sleep()方法调用以后,持有的锁是不释放的

wait():在调用wait()方法之前,必须要持有锁。在调用wait()方法以后。锁就会被释放(虚拟机进行释放),当wait方法返回时,线程会重新持有锁

notify():在调用之前,必须要持有锁。调用notify()方法本身是不会释放锁的,只有synchronized代码块执行完才释放锁

notifyAll():同notify()

比如:public synchronized void changeKm(){

this.km = 101;

notify();//当执行完这行代码时,此时还没有释放锁。

System.out.println("处理业务逻辑"); //执行完这一行代码后,才释放锁。

}

1,示例代码:sleep()方法调用以后,持有的锁识是不释放的

/**

* 验证sleep()方法,线程休眠时不会释放锁

* 当A线程拿到锁后,然后进行sleep休眠。其他线程是拿不到锁的,只能等待*/

public classSleepLock {private Object lock = newObject();//会休眠的线程类

private classThreadSleep extends Thread{

@Overridepublic voidrun() {

String threadName=Thread.currentThread().getName();//尝试去拿锁

System.out.println(threadName + "try to take the lock");try{

synchronized (lock){

System.out.println(threadName + "is taking the lock");//该线程拿到锁后,休眠5秒

Thread.sleep(5000);

System.out.println("Finish the work:"+threadName);

}

}catch(InterruptedException e){

}

}

}//不会休眠的线程类

private classThreadNotSleep extends Thread{

@Overridepublic voidrun() {

String threadName=Thread.currentThread().getName();//尝试去拿锁

System.out.println(threadName + "try to take the lock time ="+System.currentTimeMillis());

synchronized (lock){

System.out.println(threadName + "taking the lock time ="+System.currentTimeMillis());

System.out.println("Finish the work"+threadName);

}

}

}public static voidmain(String[] args) {

SleepLock sleepLock= newSleepLock();//会休眠的线程

Thread threadSleep = sleepLock.newThreadSleep();

threadSleep.setName("threadSleep");//不会休眠的线程

Thread threadNotSleep = sleepLock.newThreadNotSleep();

threadNotSleep.setName("threadNotSleep");

threadSleep.start();

threadNotSleep.start();

}

}

2,示例代码:wait()方法调用后,会释放锁

public classThreadDomain31 extends Thread{private Object lock;public ThreadDomain31(Object object){this.lock = object;

}

@Overridepublic voidrun() {try{

synchronized (lock)

{

System.out.println(Thread.currentThread().getName() + "Begin wait()");lock.wait();

System.out.println(Thread.currentThread().getName() + "End wait");

}

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

public classTest {public static voidmain(String[] args) {/**

* 输出:

* Thread-0 Begin wait()

Thread-1 Begin wait()

wait()会释放锁,不然线程2根本进不去*/Objectlock = newObject();

ThreadDomain31 mt0= new ThreadDomain31(lock);

ThreadDomain31 mt1= new ThreadDomain31(lock);

mt0.start();

mt1.start();

}

}

3,经典的生产者消费者模式演示 :wait()/notify()方法的使用

/**

* 产品*/

public classProduct {privateString name;private boolean flag = false;//生产方法

public synchronized void set(String name){

System.out.println(Thread.currentThread().getName()+"准备生产数据.....");//如果有值就等待

if (this.flag){try{

System.out.println("数据还没有被消费,生产者进行等待");this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+"开始生产数据...");

Random random= newRandom();int second = random.nextInt(5000);try{

Thread.sleep(second);

}catch(InterruptedException e) {

e.printStackTrace();

}this.name =name;this.flag = true;

System.out.println(Thread.currentThread().getName()+"生产数据完成..."+",一共花费了"+second+"ms");

System.out.println(Thread.currentThread().getName()+"通知消费者去消费数据");this.notify();//通知消费者去消费

}//消费方法

public synchronized void get(){

System.out.println(Thread.currentThread().getName()+"准备消费数据.....");//如果没有等待

if (!this.flag){try{

System.out.println("数据还没有被生产,消费者进行等待");this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+"开始消费数据...");

Random random= newRandom();int second = random.nextInt(5000);try{

Thread.sleep(second);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"消费数据完成..."+"name:"+name+""+",一共花费了"+second+"ms");this.flag = false;

System.out.println(Thread.currentThread().getName()+"通知生产者去生产数据");this.notify();//通知生产者去生产

}

}

/**

* 生产者*/

public classProducer implements Runnable{privateProduct student;publicProducer(Product student){this.student =student;

}

@Overridepublic voidrun() {while (true){

student.set("产品名称");

}

}

}

/**

* 消费者*/

public classConsumer implements Runnable{privateProduct student;publicConsumer(Product student){this.student =student;

}

@Overridepublic voidrun() {while (true){

student.get();

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值