Java多线程 二 线程间通信
Posted qiangge-python
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程 二 线程间通信相关的知识,希望对你有一定的参考价值。
线程间通信:
多个线程在处理同一资源,但是
等待唤醒机制
涉及的方法:
1、wait() 让线程处于冻结状态,被wait的线程会被存储到线程池中。
2、notify() 唤醒线程池中的一个线程(任意)
3、notifyAll() 唤醒线程池中的所有线程、、
这些方法都必须定义在同步中,
因为这些方法是用于操作线程状态的方法。
必须明确到底操作的那个锁上的线程。
为什么操作线程的方法wait notify notifyAll定义在了Object中。
因为这些方法是监视器方法,监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方法一定定义在Object类中。
package com.pzq.thread; public class SyncDemo3 public static void main(String[] args) Resource resource = new Resource(); Input input = new Input(resource); OutPut outPut = new OutPut(resource); Thread threadInput = new Thread(input); Thread threadOuput = new Thread(outPut); threadInput.start(); threadOuput.start(); class Input implements Runnable Resource r; public Input(Resource r) this.r = r; @Override public void run() int x = 0; while (true) synchronized (r) if (r.flag) try r.wait(); catch (InterruptedException e) e.printStackTrace(); if (x == 0) r.name = "mike"; r.sex = "nan"; else r.name = "丽丽"; r.sex = "女女女女女女女"; r.flag = true; r.notify(); x = (x + 1) % 2; class OutPut implements Runnable Resource r; public OutPut(Resource r) this.r = r; @Override public void run() while (true) synchronized (r) if (!r.flag) try r.wait(); catch (InterruptedException e) e.printStackTrace(); System.out.println(r.name + "......" + r.sex); r.flag = false; r.notify(); class Resource String name; String sex; boolean flag = false; public Resource() public Resource(String name, String sex) this.name = name; this.sex = sex;
生产者消费者
代码优化,将同步方法封装到属性当中
package com.pzq.thread; public class SyncDemo3 public static void main(String[] args) Resource resource = new Resource(); Input input = new Input(resource); OutPut outPut = new OutPut(resource); Thread threadInput = new Thread(input); Thread threadOuput = new Thread(outPut); threadInput.start(); threadOuput.start(); class Input implements Runnable Resource r; public Input(Resource r) this.r = r; @Override public void run() int x = 0; while (true) if (x == 0) r.set("mike", "nan"); else r.set("丽丽", "=========女"); x = (x + 1) % 2; class OutPut implements Runnable Resource r; public OutPut(Resource r) this.r = r; @Override public void run() while (true) r.out(); class Resource private String name; private String sex; private boolean flag = false; public Resource() public synchronized void set(String name, String sex) if (flag) try this.wait(); catch (InterruptedException e) e.printStackTrace(); this.name = name; this.sex = sex; flag = true; this.notify(); public synchronized void out() if (!flag) try this.wait(); catch (InterruptedException e) e.printStackTrace(); System.out.println(this.name + "....." + this.sex); flag = false; this.notify();
单生产单消费
package com.pzq.thread; public class SyncDemo4 public static void main(String[] args) Resource2 resource = new Resource2(); Producter input = new Producter(resource); Customer outPut = new Customer(resource); Thread threadInput = new Thread(input); Thread threadOuput = new Thread(outPut); threadInput.start(); threadOuput.start(); class Producter implements Runnable Resource2 r; public Producter(Resource2 r) this.r = r; @Override public void run() while (true) r.set("烤鸭"); class Customer implements Runnable Resource2 r; public Customer(Resource2 r) this.r = r; @Override public void run() while (true) r.out(); class Resource2 private String name; private boolean flag = false; private int count = 1; public Resource2() public synchronized void set(String name) if (flag) try this.wait(); catch (InterruptedException e) e.printStackTrace(); this.name = name + count; count++; System.out.println(Thread.currentThread().getName() + "生产者+++" + this.name); flag = true; this.notify(); public synchronized void out() if (!flag) try this.wait(); catch (InterruptedException e) e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "消费者" + "=================" + this.name); flag = false; this.notify();
多生产者多消费者
if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行
notify只能唤醒一个线程,如果本方唤醒了本方,就没有意义了。而且 while判断标记+notify会导致死锁。
notifyAll解决了,本方线程一定会唤醒对方线程。
package com.pzq.thread; public class SyncDemo4 public static void main(String[] args) Resource2 resource = new Resource2(); Producter input = new Producter(resource); Customer outPut = new Customer(resource); Thread threadInput1 = new Thread(input); Thread threadInput2 = new Thread(input); Thread threadInput3 = new Thread(input); Thread threadOuput1 = new Thread(outPut); Thread threadOuput2 = new Thread(outPut); Thread threadOuput3 = new Thread(outPut); Thread threadOuput4 = new Thread(outPut); Thread threadOuput5 = new Thread(outPut); threadInput1.start(); threadInput2.start(); threadInput3.start(); threadOuput1.start(); threadOuput2.start(); threadOuput3.start(); threadOuput4.start(); threadOuput5.start(); class Producter implements Runnable Resource2 r; public Producter(Resource2 r) this.r = r; @Override public void run() while (true) r.set("烤鸭"); class Customer implements Runnable Resource2 r; public Customer(Resource2 r) this.r = r; @Override public void run() while (true) r.out(); class Resource2 private String name; private boolean flag = false; private int count = 1; public Resource2() public synchronized void set(String name) while (flag) try this.wait(); catch (InterruptedException e) e.printStackTrace(); this.name = name + count; count++; System.out.println(Thread.currentThread().getName() + "生产者+++" + this.name); flag = true; this.notifyAll(); public synchronized void out() while (!flag) try this.wait(); catch (InterruptedException e) e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "消费者" + "=================" + this.name); flag = false; this.notifyAll();
多生产者多消费者 1.5新特性
jdk1.5以后将同步和锁封装成了对象。
并将操作锁的隐式方式定义到了该对象中,
将隐式动作变成了显示动作。
Lock接口:出现了替代同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。
同时更为灵活,可以一个锁上加上多组监视器。
lock() 获取锁
unlock():释放锁,通常需要定义finally代码块中
Condition接口:出现替代了Object中的wait notify notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。
可以任意锁进行组合。
await();
signal();
singnalAll
package com.pzq.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SyncDemo4 public static void main(String[] args) Resource2 resource = new Resource2(); Producter input = new Producter(resource); Customer outPut = new Customer(resource); Thread threadInput1 = new Thread(input); Thread threadInput2 = new Thread(input); Thread threadInput3 = new Thread(input); Thread threadOuput1 = new Thread(outPut); Thread threadOuput2 = new Thread(outPut); Thread threadOuput3 = new Thread(outPut); Thread threadOuput4 = new Thread(outPut); Thread threadOuput5 = new Thread(outPut); threadInput1.start(); threadInput2.start(); threadInput3.start(); threadOuput1.start(); threadOuput2.start(); threadOuput3.start(); threadOuput4.start(); threadOuput5.start(); class Producter implements Runnable Resource2 r; public Producter(Resource2 r) this.r = r; @Override public void run() while (true) r.set("烤鸭"); class Customer implements Runnable Resource2 r; public Customer(Resource2 r) this.r = r; @Override public void run() while (true) r.out(); class Resource2 private String name; private boolean flag = false; private int count = 1; // 创建一个锁对象 Lock lock = new ReentrantLock(); // 通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者 Condition con_producter = lock.newCondition(); Condition con_customer = lock.newCondition(); public Resource2() public void set(String name) lock.lock(); try while (flag) try con_producter.await(); catch (InterruptedException e) e.printStackTrace(); this.name = name + count; count++; System.out.println(Thread.currentThread().getName() + "生产者+++" + this.name); flag = true; con_customer.signal(); finally lock.unlock(); public void out() lock.lock(); try while (!flag) try con_customer.await(); catch (InterruptedException e) e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "消费者" + "=================" + this.name); flag = false; con_producter.signal(); finally lock.unlock();
定义一个容器的生产者消费者
package com.pzq.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class BoundBuffer public static void main(String[] args) Resources resources = new Resources(); Products products = new Products(resources); Customers customers = new Customers(resources); new Thread(products).start(); new Thread(products).start(); new Thread(products).start(); new Thread(customers).start(); new Thread(customers).start(); new Thread(customers).start(); class Customers implements Runnable Resources rs; public Customers(Resources rs) this.rs = rs; @Override public void run() while (true) try rs.take(); Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); class Products implements Runnable Resources rs; int count = 1; public Products(Resources rs) this.rs = rs; @Override public void run() while (true) try rs.put("烤鸭"); Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); class Resources Lock lock = new ReentrantLock(); Condition notEmpty = lock.newCondition(); Condition notFull = lock.newCondition(); Object[] buffer = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException lock.lock(); try while (count == buffer.length) notFull.await(); buffer[putptr] = x; if (++putptr == buffer.length) putptr = 0; ++count; System.out.println("-------" + Thread.currentThread().getName() + "生产了---" + (x.toString() + putptr)); notEmpty.signal(); finally lock.unlock(); public void take() throws InterruptedException lock.lock(); // Object x = null; try while (count == 0) notEmpty.await(); Object x = buffer[takeptr]; if (++takeptr == buffer.length) takeptr = 0; --count; System.out.println("#######" + Thread.currentThread().getName() + "消费了####" + (x.toString() + takeptr)); notFull.signal(); finally lock.unlock(); // return x;
以上是关于Java多线程 二 线程间通信的主要内容,如果未能解决你的问题,请参考以下文章