`
Luob.
  • 浏览: 1588886 次
  • 来自: 上海
社区版块
存档分类
最新评论

java之12天 多线程 (一)

    博客分类:
  • Java
阅读更多
线程间通信问题
/**
 * 线程间通信问题
 *   其实就是多个线程在操作通过一个资源,但是操作的动作不同.
 * 
 * 同步的前提:
 * 1.必须要有两个或者两个以上的线程
 * 2.必须是多个线程使用同一个锁
 *
 * 等待唤醒机制 
 *  
 *  wait()
 *  notify()
 *  notifyAll();
 *  
 *  都使用在同步中,因为要对持有监视器的线程操作,所以要使用在 同步中,因为只有 同步才具有锁.
 *  
 *  为什么这些操作线程的方法要定义在Object类中呢?
 *  因为 这些方法 在操作同步中线程时,都必须要表示他们所操作线程的只有的锁.
 *  只有 同一个锁上的 被等待线程,可以被同一个锁上的notify唤醒
 *  不可以对不同锁中的线程进行唤醒.
 *  
 *  也就是,等待和唤醒 必须是同一个锁
 *  而锁可以是任意对象,所以可以被任意对象调用的 方法定义在 Object中
 *  
 *  
 *  
 */
class Resource{
	 String name;
	 String sex;
	 boolean flag=false;  //表示没有值
}

//复制
class Input implements Runnable{
	
	Resource r;
	Input(Resource r){
		this.r=r;
	}
	//Object obj=new Object();
	public void run(){
		int x=0;
		while(true){
			synchronized(r){ //obj -->this--> input.class(Output.class,InputOutputDemo.class)-->r
				if(r.flag){
					try {
						r.wait();  //线程运行的时候,程序会在内存中创建线程池,等待的线程会存在线程中 
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(x==0){
					r.name="mike";
					r.sex="man";
				}else{
					r.name="丽丽";
					r.sex="女女女女";
				}
				r.flag=true;
				r.notify();//唤醒 输出线程  通常会唤醒 线程池中 第一被等待的线程
			}
			x=(x+1)%2;
		}
	}
}

//取出后 然后输出
class Output implements Runnable{
	Resource r;
	Output(Resource r){
		this.r=r;
	}
	//Object obj=new Object();
	public void run(){
		while(true){
			synchronized(r){ //obj -->this--> input.class(Output.class,InputOutputDemo.class)-->r
				if(!r.flag)  
					try {
						r.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.println(r.name+"--------------"+r.sex);
				r.flag=false;
				r.notify();
			}
		}
	}
	
}

public class InputOutputDemo {
	public static void main(String[] args) {
		
		Resource r=new Resource();
		
		Input in=new Input(r);
		Output out=new Output(r);
		
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
	
		t1.start();
		t2.start();
	}

}




优化上面的 等待唤醒机制
/**
 * 线程间通信问题
 *   其实就是多个线程在操作通过一个资源,但是操作的动作不同.
 * 
 * 同步的前提:
 * 1.必须要有两个或者两个以上的线程
 * 2.必须是多个线程使用同一个锁
 *
 * 等待唤醒机制 
 *  
 * 对上面的程序进行优化
 */
class Resource{
	 private String name;
	 private String sex;
	 private  boolean flag=false;  //表示没有值
	 
	 public synchronized void setValue(String name,String sex){
		 
		 if(flag){
			try{
				this.wait();  //线程运行的时候,程序会在内存中创建线程池,等待的线程会存在线程中 
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		 }
		 this.name=name;
		 this.sex=sex;
		 flag=true;
		 this.notify();
	 }
	 
	 public synchronized void out(){
		 if(!flag){
			try{
				this.wait();  //线程运行的时候,程序会在内存中创建线程池,等待的线程会存在线程中 
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		 }
		 System.out.println(name+"--------------"+sex);
		 flag=false;
		 this.notify();
	 }
	  
}


class Input implements Runnable{
	
	Resource r;
	Input(Resource r){
		this.r=r;
	}
	//Object obj=new Object();
	public void run(){
		int x=0;
		while(true){
			if(x==0){
				r.setValue("mike", "man");
			}else{
				r.setValue("莉莉", "女女");
			}
			x=(x+1)%2;
		}
	}
}

//取出后 然后输出
class Output implements Runnable{
	Resource r;
	Output(Resource r){
		this.r=r;
	}
	//Object obj=new Object();
	public void run(){
		while(true){
			r.out();
		}
	}
	
}

public class InputOutputDemo {
	public static void main(String[] args) {
		
		Resource r=new Resource();
		
		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
		
		/*Input in=new Input(r);
		Output out=new Output(r);
		
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		
		t1.start();
		t2.start();*/
	}

}


线程间通信 ,生产者 和消费者
/** 线程间通信 ,生产者 和消费者
 * 
 * 发现 上面的  等待唤醒机制 中 如果 线程数 超过过两个  使用  notify 就有问题了  
 *   原因 就是  当一个线程等待后  被其他线程 唤醒  就不会判断  flag 为真 为假 ,这样就会在某一时间段就会 生产多个商品  或者 消费多个商品
 *
 */
class Resouce{
	
	private String name;
	private int count=1;
	private boolean flag=false;
	
//	while(true){ //t1  t3  循环一次后发现 不一定 
		public synchronized void setValue(String name){
			while(flag)
				try {  
					this.wait();
				} catch (InterruptedException e) {// t1 (1等待--->5运行  )   t3  (2等待  --6 运行)
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			this.name=name+"...."+count++;
			System.out.println(Thread.currentThread().getName()+"....生产者...."+this.name);
			flag=true;
			//this.notify()  // 只唤醒线程中 最先等待那一个线程
			this.notifyAll();
		}
	//}
	
	public synchronized void out(){
		while(!flag)
			try {  
				this.wait();// t1 (3等待)   t3  (4等待)
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		System.out.println(Thread.currentThread().getName()+"...........消费者............."+this.name);
		flag=false;
		this.notifyAll();
	}
	
}
class Producer implements Runnable{
	
	Resouce r;
	Producer(Resouce r){
		this.r=r;
	}
	
	public void run(){
		while(true){
			r.setValue("+商品+");
		}
	}
}


class Consumer implements Runnable{
	
	Resouce r;
	Consumer(Resouce r){
		this.r=r;
	}
	
	public void run(){
		while(true){
			r.out();
		}
	}
}


public class ProducerConsumerDemo {

	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Resouce r=new Resouce();
		
		Producer p=new Producer(r);
		Consumer c=new Consumer(r);
		
		Thread t1=new Thread(p);
		Thread t2=new Thread(c);
		
		//使用 两个线程的时候  仿照 之前的  例子是没有问题,如果 超过两个线程后就会有问题了 
		Thread t3=new Thread(p);
		Thread t4=new Thread(c);
		
		t1.start();
		t2.start();
		
		//  因此 使用上  了 while  notifyAll   才解决这个问题  这是JDK1.5之前 的程序都这么干的 
		t3.start();
		t4.start();
	}


使用 JDK1.5的新特性 来优化上面的代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * JDK5.0 中提供了 多线程 升级解决方案
 * 将同步Synchronized 替换成  显示的 Lock机制
 * 将 Object 中的 wait notify  notifyall 替换成了 Condition对象中 await signal  signalAll
 * 
 * Condition 对象可以用  Lock 锁,进行获取
 * 
 * 在该实例中 实现了本方 只唤醒 对方的操作
 *
 */
class Resouce{
	
	private String name;
	private int count=1;
	private boolean flag=false;
	
	private Lock lock=new ReentrantLock();
	
	private Condition c_proc=lock.newCondition();  //声明 一个锁中  监视器对象
	private Condition c_cons=lock.newCondition();  //声明 一个锁中  监视器对象
	
	
	public  void setValue(String name) throws InterruptedException{
		lock.lock();   //synchronized
		try{
		while(flag)
			c_proc.await();   //this.wait()
			this.name=name+"...."+count++;
			System.out.println(Thread.currentThread().getName()+"....生产者...."+this.name);
			flag=true;
		}finally{  //释放锁的动作一定要执行
			//this.notify()  // 只唤醒线程中 最先等待那一个线程
			//this.notifyAll();
			c_cons.signal();   //只需要唤醒 消费者中的一个就可以了 不需要 All
		}
	}
	
	
	public  void out() throws InterruptedException{
		lock.lock();  //synchronized    一看就知道是同一个锁 是吧 呵呵 
		try{
			while(!flag)
			c_cons.await();  // this.wait();
			System.out.println(Thread.currentThread().getName()+"...........消费者............."+this.name);
			flag=false;
		}finally{
			//this.notifyAll();
			c_proc.signal(); // 唤醒生产者中的一个就可以了
		}
	}
	
}
//生产者
class Producer implements Runnable{
	
	Resouce r;
	Producer(Resouce r){
		this.r=r;
	}
	
	public void run(){
		while(true){
			try {
				r.setValue("+商品+");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

//消费者
class Consumer implements Runnable{
	
	Resouce r;
	Consumer(Resouce r){
		this.r=r;
	}
	
	public void run(){
		while(true){
			try {
				r.out();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}


public class ProducerConsumerDemo {

	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Resouce r=new Resouce();
		
		Producer p=new Producer(r);
		Consumer c=new Consumer(r);
		
		Thread t1=new Thread(p);
		Thread t2=new Thread(c);
		Thread t3=new Thread(p);
		Thread t4=new Thread(c);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}
0
6
分享到:
评论

相关推荐

    JAVA12天全掌握

    【JAVA12天全掌握】课程旨在帮助学员在12天内系统地理解和掌握Java编程语言的核心概念和技术。这不仅是一场快速学习的挑战,也是一个深度理解Java编程基础的全面之旅。通过本课程,学员将从零开始,逐步建立起扎实的...

    java教程-每日一课,27天java从入门到进阶

    第12天:字符串王者地位 第13天:算法工具类包装类 第14天:正则及其他类 第15-18天:数组到集合 第19天:文件操作IO 第20、21天:IO流文件操作类图 第22天:其他流 第23天:多线程 第24天:多线程深入 第25天:GUI ...

    初学者必看多线程倒计时器

    本文介绍了如何使用Java Swing GUI框架、多线程以及日期时间处理技术来实现一个简单的多线程倒计时器。通过这个例子,读者可以了解到如何在Java中构建GUI应用程序,如何利用多线程来实现后台任务的并发执行,以及...

    java100天速成

    6. **多线程**:Java对多线程的支持非常强大,你需要学习如何创建和管理线程,理解同步与互斥,以及线程池的概念,这对提升程序性能有很大帮助。 7. **网络编程**:Java的Socket编程能让你构建网络应用程序,理解...

    韩顺平30天学java

    12. **反射**:通过反射机制,可以在运行时动态地获取类的信息并操作对象,这是Java高级特性之一。 13. **泛型**:泛型提供了一种在编译时检查类型安全的方法,同时允许程序员编写更灵活的代码。 14. **Java API的...

    初学Java时花费12天做的一款小游戏.zip

    标题中的“初学Java时花费12天做的一款小游戏”表明这是一个初级Java程序员为了学习和实践编程技能而创建的小型游戏项目。这个项目可能包含了基本的编程概念、面向对象设计原则以及简单的游戏逻辑。在12天的时间内,...

    java入门第一课

    Java入门第一课主要针对初学者,...此外,随着课程的深入,可能还会涉及到更多高级主题,如集合框架、多线程、网络编程等。对于持续更新的课程,可能还会有新的特性和实践案例添加进来,以保持内容的时效性和实用性。

    一个简易的JAVA数字时钟支持24时12时转换

    1. **时间处理类**: Java中的`java.time`包提供了处理时间的类,如`LocalTime`,它是用来表示一天中的时间(小时、分钟、秒、纳秒)。在这个数字时钟程序中,`LocalTime.now()`可能被用来获取当前时间。 2. **24...

    21天学好JAVA

    7. **多线程编程**:了解线程的概念,学习Thread类和Runnable接口,掌握同步和异步操作,以及线程间的通信。 8. **JAVA Swing和JavaFX**:学习如何使用JAVA创建图形用户界面(GUI),掌握Swing组件库的使用,或者更...

    21天学通java的源代码

    《21天学通Java》是一本面向初学者的编程教程,旨在帮助读者在短时间内掌握Java编程基础。这本书由庞永庆、庞丽娟等人编著,提供了丰富的实例和实践练习,以帮助学习者深入理解Java语言的核心概念。源代码是书中各个...

    21天精通java源代码

    6. **多线程**:Java提供了对多线程的支持,理解线程的创建、同步和通信,可以实现高效的并发处理。 7. **反射机制**:反射是Java的一大特色,它允许在运行时检查类、接口、字段和方法的信息,甚至动态调用方法。 ...

    27天成为Java大神

    6. **多线程**:Java内置了对多线程的支持,包括Thread类、Runnable接口,以及同步控制方法(如synchronized关键字、wait()、notify()和notifyAll())。 7. **反射API**:Java反射机制允许在运行时动态地获取类的...

    java基础18天Typora笔记

    多线程编程是Java的一个重要特性,通过实现Runnable接口或继承Thread类创建线程。了解并发控制(synchronized关键字、wait/notify机制)、线程状态以及线程池的概念。 9. **文件与文件系统** 学习File类用于文件...

    java视频教程_黑马Java零基础辅导班[第二期]12天课件源码

    总之,本Java视频教程结合黑马Java零基础辅导班的12天课件和源码,为初学者提供了一个系统学习Java的平台。通过深入学习和实践,你将能掌握Java编程的基本技能,为进一步深入学习Java的高级特性和框架打下坚实基础。

    21天学会java光盘电子教案(PPT).

    9. **多线程**:Java内置了对多线程的支持,你可以通过实现Runnable接口或继承Thread类来创建线程。 10. **Swing和JavaFX**:对于图形用户界面(GUI)开发,Java提供了Swing和JavaFX库。这两个库包含了各种组件和...

    21天学java源代码

    9. **多线程**:Java内置了对多线程的支持,学习者需要理解线程的创建、同步、生命周期管理等概念。 10. **文件和目录操作**:Java提供了File类来处理文件和目录,包括创建、删除、重命名等操作。 11. **Swing和...

    21天学java培训笔记和代码

    11. **多线程**:Java内置了多线程支持,通过Thread类或实现Runnable接口创建并管理线程,实现并发执行。 12. **Swing与JavaFX**:Java提供GUI(图形用户界面)工具包,如Swing和JavaFX,用于构建桌面应用。 13. *...

    Java 21天学通java

    9. **多线程**:Java支持多线程编程,通过Thread类和Runnable接口可以创建并管理多个执行线程,提高程序的并发性能。 10. **Java Swing和JavaFX**:这两是Java的图形用户界面(GUI)库,用于构建桌面应用程序。...

    21天学通Java.第7版-中文版-良心积分价

    10. **多线程**:Java内置了对多线程的支持,通过实现Runnable接口或继承Thread类来创建线程。了解线程的同步和通信机制,如synchronized关键字、wait()、notify()和notifyAll()方法。 11. **文件和目录操作**:...

Global site tag (gtag.js) - Google Analytics