java多线程:线程的通信、唤醒等待机制、生产消费者模式、Lock
2018-09-19 19:34
603 查看
线程的通信:打印机打印–不断的输入输出
package com.qianfeng.test; /* * 线程的通信: * 分析: * 需要两个线程--输入线程和输出线程 * 需要两个任务--输入任务和输出任务 * 需要一份数据 * * 实现:打印机打印--不断的输入不断的输出 * */ public class Demo2 { public static void main(String[] args) { //1.创建数据类对象 Des des =new Des(); //创建任务类对象并绑定数据 Input input = new Input(des); Output output = new Output(des); //3.创建线程 Thread inputThread = new Thread(input); Thread outputThread = new Thread(output); //4.开启线程 inputThread.start(); outputThread.start(); } } //创建数据类 class Des{ String name; String sex; } //创建输入任务 class Input implements Runnable{ Des des; public Input(Des des){ this.des=des; } public void run() { /* * 分析:需要输入任务与输出任务共用一把锁,保证两个任务之间是同步的。 * 给两个任务加一把锁,锁可以是des或Object.class * * 不建议使用Object.class,因为Object.class应用范围太大,其它地方可能也会用到。 * 使用des最合适,因为它只被两个线程共享。 * * 注意:只给一个任务加锁无法实现两个线程的同步。 */ int i = 0; while(true){ synchronized (des) { if (i==1) { des.name = "凤姐"; des.sex = "男" ; }else { des.name = "芙蓉姐姐"; des.sex = "女" ; } i=(i+1)%2; } } } } //创建输出任务 class Output implements Runnable{ Des des; public Output(Des des){ this.des=des; } public void run() { while(true){ synchronized (des) { System.out.println("姓名:"+des.name+" 性别"+des.sex); } } } }
唤醒等待机制,wait()/notify()/notifyAll()
package com.qianfeng.test; /* * 线程的通信: * 分析: * 需要两个线程--输入线程和输出线程 * 需要两个任务--输入任务和输出任务 * 需要一份数据 * * 实现:打印机打印--一次输入一次输出 * * 使用唤醒等待机制实现:wait()/notify()/notifyAll()等 * wait():让当前的线程进入等待的状态,他会被放入一个池子(线程池),失去了抢cpu的能力,等待唤醒。(锁--相当于给当前线程做了一个标记) * notify():让当前的线程从等待线程唤醒,相当于从池子中取出线程。(唤醒的是同一把锁下的任意一个线程) * notifyAll():唤醒的是同一把锁下的所有线程。 */ public class Demo3 { public static void main(String[] args) { // 1.创建数据类对象 Des1 des = new Des1(); // 创建任务类对象并绑定数据 Input1 input = new Input1(des); Output1 output = new Output1(des); // 3.创建线程 Thread inputThread = new Thread(input); Thread outputThread = new Thread(output); // 4.开启线程 inputThread.start(); outputThread.start(); } } // 创建数据类 // 封装类的原则:是你的活你做,不是你的活不要做。 class Des1 { String name; String sex; boolean flag = false;// 创建一个标识,控制唤醒与等待的切换。 // 获取数据--处理输入 public synchronized void setData(String name, String sex) { if (flag == true) { try {// 让输入线程等待,当flag值为true的时候 // 在执行代码的时候,这里对应的是哪个线程,锁对象操作的就是哪个线程。 wait();// 只要一执行wait,线程会立刻停在这里,等待下次唤醒。 } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name; this.sex = sex; flag = !flag; //// 唤醒输出线程。 // 当执行唤醒的时候,在线程池中没有找到被当前的锁标记的线程,我们称为空唤醒,空唤醒对程序没有影响,程序允许空唤醒。 notify(); } // 将数据打印到控制台--处理输出 public synchronized void getData() { if (flag == false) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("姓名:" + name + " 性别" + sex); flag = !flag; notify(); } } // 创建输入任务 class Input1 implements Runnable { Des1 des; public Input1(Des1 des) { this.des = des; } public void run() { int i = 0; while (true) { if (i == 1) { des.setData("凤姐", "男"); } else { des.setData("芙蓉姐姐", "女"); } i = (i + 1) % 2; } } } // 创建输出任务 class Output1 implements Runnable { Des1 des; public Output1(Des1 des) { this.des = des; } public void run() { while(true){ des.getData(); } } }
多线程设计模式:单生产者单消费者
package com.qianfeng.test; /* * 多线程的设计模式:生产者消费者 * 两类: * 1.单生产者单消费者 * 2.多生产者多消费者 * * 先研究单生产者单消费者 * 分析: * 生产线程,消费线程 * 生产任务,消费任务 * 产品 */ public class Demo4 { public static void main(String[] args) { //1.创建产品 Product product = new Product(); //2.创建生产任务,消费任务 Producer producer = new Producer(product); Consumer consumer = new Consumer(product); //3.创建生产线程,消费线程 Thread t1 = new Thread(producer); Thread t2 = new Thread(consumer); //4.开启线程 t1.start(); t2.start(); } } //创建产品类 class Product{ String name; double price; int count; boolean flag = false;//用来在唤醒与等待之间进行切换 //为生产准备数据 public synchronized void setProduce(String name,double price){ if (flag == true) { try { wait();//让生产线程等待 } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name; this.price = price; System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); count++; flag = ! flag; notify();//唤醒消费线程 } //为消费准备数据 public synchronized void consume() { if (flag == false) { try { wait();//让消费线程等待 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); flag = ! flag; notify();//唤醒生产线程 } } //创建生产任务 class Producer implements Runnable{ Product product; public Producer(Product product) { super(); this.product = product; } public void run() { while (true) { product.setProduce("bingbing", 10); } } } //创建消费任务 class Consumer implements Runnable{ Product product; public Consumer(Product product) { super(); this.product = product; } public void run() { while (true) { product.consume(); } } }
多线程设计模式:多生产者多消费者
package com.qianfeng.test; /* * 多线程的设计模式:生产者消费者 * 两类: * 1.单生产者单消费者 * 2.多生产者多消费者 * * 研究多生产者多消费者 * 分析: * 生产线程,消费线程有多个 * 生产任务,消费任务各有一个 * 产品一个 */ public class Demo5 { public static void main(String[] args) { //1.创建产品 Product1 product = new Product1(); //2.创建生产任务,消费任务 Producer1 producer = new Producer1(product); Consumer1 consumer = new Consumer1(product); //3.创建生产线程,消费线程 Thread t0 = new Thread(producer); Thread t1 = new Thread(producer); Thread t2 = new Thread(consumer); Thread t3 = new Thread(consumer); //4.开启线程 t0.start(); t1.start(); t2.start(); t3.start(); } } //创建产品类 class Product1{ String name; double price; int count; boolean flag = false;//用来在唤醒与等待之间进行切换 //为生产准备数据 public synchronized void setProduce(String name,double price){ while (flag == true) { try { wait();//让生产线程等待 } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name; this.price = price; System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); count++; flag = ! flag; //notify();//唤醒消费线程 notifyAll(); } //为消费准备数据 public synchronized void consume() { while (flag == false) { try { wait();//让消费线程等待 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); flag = ! flag; //notify();//唤醒生产线程 notifyAll(); } } //创建生产任务 class Producer1 implements Runnable{ Product1 product; public Producer1(Product1 product) { super(); this.product = product; } public void run() { while (true) { product.setProduce("bingbing", 10); } } } //创建消费任务 class Consumer1 implements Runnable{ Product1 product; public Consumer1(Product1 product) { super(); this.product = product; } public void run() { while (true) { product.consume(); } } }
Lock,Condition。Lock与synchronized的比较
package com.qianfeng.test; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * Lock: * 比较synchronized和Lock * 1.synchronized:从jdk1.0开始使用----隐式同步 * synchronized(锁对象){//获取锁 我们将这里的锁称为锁旗舰或者监听器 * 同步的代码 * }//释放锁 * 2.Lock:从jdk1.5开始使用----显示同步 * 原理:Lock是接口,我们要通过他的子类工作 * 具体的工作流程: * 首先调用lock的lock()方法,获取锁 * 进行同步操作的代码 * 调用lock的unlock()方法,释放锁 * * 使用场景总结: * 1.当进行多生产者的消费者的时候,使用lock,其他的使用synchronized * * 使用效率上lock比synchronized高. */ public class Demo6 { public static void main(String[] args) { //1.创建产品 Product2 product = new Product2(); //2.创建生产任务,消费任务 Producer2 producer = new Producer2(product); Consumer2 consumer = new Consumer2(product); //3.创建生产线程,消费线程 Thread t0 = new Thread(producer); Thread t1 = new Thread(producer); Thread t2 = new Thread(consumer); Thread t3 = new Thread(consumer); //4.开启线程 t0.start(); t1.start(); t2.start(); t3.start(); } } //创建产品类 class Product2{ String name; double price; int count; boolean flag = false;//用来在唤醒与等待之间进行切换 //创建Lock的对象 Lock lock = new ReentrantLock(); //创建用于生产线程的Condition对象 Condition proCon = lock.newCondition(); //创建用于消费线程的Condition对象 Condition conCon = lock.newCondition(); //为生产准备数据 public void setProduce(String name,double price){ try { lock.lock();//获取锁 while (flag == true) { try { //wait();//让生产线程等待 proCon.await(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name; this.price = price; System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); count++; flag = ! flag; //notify();//唤醒消费线程 //notifyAll(); conCon.signal(); } finally {//必须执行的代码 lock.unlock();//释放锁 } } //为消费准备数据 public void consume() { try { lock.lock(); while (flag == false) { try { //wait();//让消费线程等待 conCon.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); flag = ! flag; //notify();//唤醒生产线程 //notifyAll(); proCon.signal(); } finally { lock.unlock(); } } } //创建生产任务 class Producer2 implements Runnable{ Product2 product; public Producer2(Product2 product) { super(); this.product = product; } public void run() { while (true) { product.setProduce("bingbing", 10); } } } //创建消费任务 class Consumer2 implements Runnable{ Product2 product; public Consumer2(Product2 product) { super(); this.product = product; } public void run() { while (true) { product.consume(); } } }
守护线程,setDaemon。
package com.qianfeng.test; /* * 守护线程:相当于后台线程,依赖于前台线程。正常情况下,当前台线程结束的时候,不管后台线程有没有结束,都会立即结束。 * 典型的守护线程:垃圾回收线程。 * */ public class Demo7 { public static void main(String[] args) { Test test = new Test(); Thread thread = new Thread(test); /* * 当程序调用setDaemon的时候,并且将参数设置为true,他就变成了守护线程。 * 注意:这个方法一定要在start方法之前调用。 */ thread.setDaemon(true); thread.start(); int i = 0; while(true){ if (i++ == 10 ) { System.out.println(Thread.currentThread().getName()+" i"+i); break;//主线程结束 } } } } class Test implements Runnable{ public void run() { while(true){ System.out.println("守护线程"); } } }
join方法
package com.qianfeng.test; /* * join()方法: * 原理:程序一旦调用了join方法,他的优先级会高于主线程。意思是说,主线程会等当前线程执行完后再去执行。 * 注意:这个线程的优先级只比main高,对其它的线程没有影响。 * */ public class Demo8 { public static void main(String[] args) { Dog dog = new Dog(); Thread thread0 = new Thread(dog); Thread thread1 = new Thread(dog); thread0.start(); thread1.start(); /* * 当线程开始工作后,让thread0调用join()方法,它的优先级会高于main线程。 * 注意:join()方法必须在线程开始工作后执行 */ try { thread0.join(); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+" i"+i); } } } class Dog implements Runnable{ public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+" i"+i); } } }阅读更多
相关文章推荐
- 多线程__【线程间通信】【等待唤醒机制】【多生产多消费】【Lock&Condition接口】
- 多线程__【线程间通信】【等待唤醒机制】【多生产多消费】【Lock&Condition接口】
- java多线程之 生产者和消费者 线程间通信 等待与唤醒机制
- 【我的Java笔记】多线程_等待唤醒机制(生产消费者模式)
- 多线程等待唤醒机制之生产消费者模式
- java多线程——线程间通信之线程等待唤醒机制
- Java多线程四:线程间通信/等待唤醒机制
- java多线程(2):线程通信之生产者消费者模式及等待唤醒机制
- 多线程等待唤醒机制之生产消费者模式
- 多线程等待唤醒机制之生产消费者模式
- Java基础学习5_多线程(线程间通信--等待唤醒机制)
- day12线程间的通信,等待唤醒机制,生产者消费者问题。新锁lock(): 守护线程,interrupt()停止线程用,join()yield()
- 24 API-多线程(多线程(多线程JDK5Lock锁,生产者消费者等待唤醒机制,定时器),设计模式(设计原则,设计模式(简单工程,工厂方法,单例模式)
- 多线程等待唤醒机制之生产消费者模式
- 多线程等待唤醒机制之生产消费者模式
- 线程间通信、等待唤醒机制、生产者消费者问题(Lock,Condition)、停止线程和守护线程、线程优先级
- 多线程等待唤醒机制之生产消费者模式
- Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解
- (九)Java入门--多线程(4)线程通信--等待唤醒机制
- JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制