本文共 6083 字,大约阅读时间需要 20 分钟。
在多线程的开发过程之中最为著名的案例就是生产者与消费者操作,该操作的主要流程如下:
可以将生产者与消费者定义为两个独立的线程类对象,但是对于现在生产的数据,可以使用如下的组成:
package com.thread;public class Threademo { public static void main(String[] args) { Message msg = new Message(); new Thread(new Producer(msg)).start(); new Thread(new Customer(msg)).start(); }}/** * 中间数据类 */class Message{ private String title; private String content; public String getContent() { return content; } public String getTitle() { return title; } public void setContent(String content) { this.content = content; } public void setTitle(String title) { this.title = title; }}/** * 生产者 */class Producer implements Runnable{ private Message msg; public Producer(Message msg) { this.msg = msg; } @Override public void run() { for(int x = 0; x < 100 ; x ++) { if( x % 2 == 0){ this.msg.setTitle("王建"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.msg.setContent("y宇宙大帅哥"); } else { this.msg.setTitle("小高"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.msg.setContent("猥琐第一个人,保持常态"); } } }}class Customer implements Runnable{ private Message msg; public Customer(Message msg){ this.msg = msg; } @Override public void run() { for(int x = 0 ; x < 100 ; x ++){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.msg.getTitle() + "," + this.msg.getContent()); } }}
通过真个代码的执行,你会发现此时有两个主要问题:
如果要解决问题,首先解决的就是数据同步的处理问题,如果想要解决数据同步最简单的做法就是使用synchronized定义同步代码块或同步方法,于是这个时候对于同步的处理就可以直接在Message类中完成。
范例:解决同步操作package com.thread;/** * 中间数据类 */class Message{ private String title; private String content; public synchronized void set(String title,String content) { this.title = title; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.content = content; } public synchronized String get(){ return this.title + "," + this.content; }}public class Threademo { public static void main(String[] args) { Message msg = new Message(); new Thread(new Producer(msg)).start(); new Thread(new Customer(msg)).start(); }}/** * 生产者 */class Producer implements Runnable{ private Message msg; public Producer(Message msg) { this.msg = msg; } @Override public void run() { for(int x = 0; x < 100 ; x ++) { if( x % 2 == 0){ this.msg.set("王建","宇宙大帅哥"); } else { this.msg.set("小高","猥琐第一个人,保持常态"); } } }}class Customer implements Runnable{ private Message msg; public Customer(Message msg){ this.msg = msg; } @Override public void run() { for(int x = 0 ; x < 100 ; x ++){ System.out.println(this.msg.get()); } }}
在进行同步处理的时候肯定需要一个同步的处理对象,那么我们此时肯定要将同步操作交个Message类操作最合适了。这个时候发现数据已经可以正常的保持一致了,但是对于重复操作的问题依然存在。
如果说现在要想解决生产者与消费者的问题,那么最好的解决方法就是使用等待与唤醒机制。而对于等待与唤醒的机制主要依靠的是Object类中提供的方法处理的。
public final void wait() throws InterruptedException;
2、设置等待时间:public final void wait(long timeout)throws InterruptedException;
3、设置等待时间:public final void wait(long timeout,int nanos)throws InterruptedException;
public final void notify()
;public final void notifyAll()
; 如果此时有若干个等待线程的话,那么notify()表示的是唤醒等待第一个等待的,而其他的线程继续等待,而notifyAll()表示唤醒所有等待的线程,哪个线程的优先级高就有可能先执行。 对于当前的问题主要解决应该通过Message类完成处理。 范例:修改Message类class Message{ private String title; private String content; private boolean flag = true; //生产或消费的形式 public synchronized void set(String title,String content) { if(this.flag == false){ try { super.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.title = title; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.content = content; this.flag = false; // 已经生产过了 super.notify(); //唤醒线程 } public synchronized String get(){ if(this.flag == true){ //还未生产需要等待 try { super.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { return this.title + "," + this.content; } finally { this.flag = true; // 可以继续生产 super.notify(); //唤醒线程 } }}public class Threademo { public static void main(String[] args) { Message msg = new Message(); new Thread(new Producer(msg)).start(); new Thread(new Customer(msg)).start(); }}/** * 生产者 */class Producer implements Runnable{ private Message msg; public Producer(Message msg) { this.msg = msg; } @Override public void run() { for(int x = 0; x < 100 ; x ++) { if( x % 2 == 0){ this.msg.set("王建","宇宙大帅哥"); } else { this.msg.set("小高","猥琐第一个人,保持常态"); } } }}class Customer implements Runnable{ private Message msg; public Customer(Message msg){ this.msg = msg; } @Override public void run() { for(int x = 0 ; x < 100 ; x ++){ System.out.println(this.msg.get()); } }}
这种处理形式就是在进行多线程开发过程中最原始的处理方案,整个的等待、同步、唤醒机制都是由开发者自行通过原生代码实现控制。
转载地址:http://wnfoi.baihongyu.com/