java多线程的等待唤醒机制及如何解决同步过程中的安全问题

简介: /* class Person{ String name; String sex; boolean flag = true; public void setPerson(String name, String sex){ this.
/* 
class Person{
   String name;
   String sex;
   boolean flag = true;
   public void setPerson(String name, String sex){  
				 this.sex=sex;
				 this.name=name;   
   }
}
class Input implements Runnable{
   int x=0;
   Person p;
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
		   if(x==1){
			  p.setPerson("hjz", "man");
		   }
		   else p.setPerson("哈哈哈", "女女女女");
		   x=(x+1)%2;
	   }
   } 
}

class Output implements Runnable{
   int x=0;
   Person p;
   Output(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	       System.out.println(p.name + "....." + p.sex);
	   }
   } 
} 
public class Test{
    public static void main(String[] args){
	     Person p = new Person();
		 new Thread(new Input(p)).start();
		 new Thread(new Output(p)).start();
	}
}
*/

/*
输出的结果:
哈哈哈.....man
hjz.....man
hjz.....man
哈哈哈.....man
hjz.....女女女女
*/

//线程安全隐患出现:首先考虑到是多线程操作了同一资源,所以要用同步!
/* 
class Person{
   String name;
   String sex;
   boolean flag = true;
   public void setPerson(String name, String sex){  
				 this.sex=sex;
				 this.name=name;   
   }
}

class Input implements Runnable{
   int x=0;
   Person p;
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	      synchronized(new Object()){
			   if(x==1){
				  p.setPerson("hjz", "man");
			   }
			   else p.setPerson("哈哈哈", "女女女女");
			   x=(x+1)%2;
		  }
	   }
   } 
}

class Output implements Runnable{
   int x=0;
   Person p;
   Output(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	       System.out.println(p.name + "....." + p.sex);
	   }
   } 
}
public class Test{
    public static void main(String[] args){
	     Person p = new Person();
		 new Thread(new Input(p)).start();
		 new Thread(new Output(p)).start();
	}
}
 */

//同步完成之后,发现还是出现安全隐患的情况,在考虑一下是否访问统一资源的多个线程用的是同一个锁!
//本例中的应将输入输出一起同步(注意输入输出不在同一个线程之中,输出线程不会获得 Person p对象的控制权!)
/*   class Input implements Runnable{
   int x=0;
   Person p;
   
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	      synchronized(p){
		       if(p.flag){
			     try{
					 p.wait();
				   }catch(InterruptedException e){
				   }
			   }
		       if(!p.flag){
				   if(x==1){
					  p.setPerson("hjz", "man");
				   }
				   else p.setPerson("哈哈哈", "女女女女");
				   x=(x+1)%2;
			   }
			   
			   p.flag=true;
			   p.notify();
			   
		  }
	   }
   } 
} */


//现在的代码是将同步放到函数里!真正开发过的时候就是这样实现,也就是我们多个线程同事操作一个类对象
//调用该类提供的对外方法,并将调用的方法进行同步!防止安全隐患!
class Person{
   String name;
   String sex;
   boolean flag = true;
   public void setPerson(String name, String sex){
       synchronized(this){
	     if(!flag){
		     try{
			    wait();
			 }catch(InterruptedException e){}
		 }
	     if(flag){
				 this.sex=sex;
				 try{
					Thread.sleep(100);
				 }catch(InterruptedException e){}
				 this.name=name;
	     }
		 flag=false;
		 notify();
	   }
   }
   
   public void outPerson(){
      synchronized(this){
	      if(flag){
		     try{
			     wait();
			 }catch(InterruptedException e){}
		  }
		  if(!flag){
		      System.out.println(name + "....." + sex);
		  }
		  flag=true;
		  notify();
	  }
   }
}

class Input implements Runnable{
   int x=0;
   Person p;
   
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
				   if(x==1){
					  p.setPerson("hjz", "man");
				   }
				   else p.setPerson("哈哈哈", "女女女女");
				   x=(x+1)%2;
	   }
   } 
}

class Output implements Runnable{
   int x=0;
   Person p;
   Output(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	       p.outPerson();
	   }
   } 
}  


public class Test{
    public static void main(String[] args){
	     Person p = new Person();
		 new Thread(new Input(p)).start();
		 new Thread(new Output(p)).start();
	}
}

  

目录
相关文章
|
4月前
|
设计模式 人工智能 安全
AQS:Java 中悲观锁的底层实现机制
AQS(AbstractQueuedSynchronizer)是Java并发包中实现同步组件的基础工具,支持锁(如ReentrantLock、ReadWriteLock)和线程同步工具类(如CountDownLatch、Semaphore)等。Doug Lea设计AQS旨在抽象基础同步操作,简化同步组件构建。 使用AQS需实现`tryAcquire(int arg)`和`tryRelease(int arg)`方法以获取和释放资源,共享模式还需实现`tryAcquireShared(int arg)`和`tryReleaseShared(int arg)`。
186 32
AQS:Java 中悲观锁的底层实现机制
|
2月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
112 0
|
4月前
|
人工智能 Java 关系型数据库
Java——SPI机制详解
SPI(Service Provider Interface)是JDK内置的服务提供发现机制,主要用于框架扩展和组件替换。通过在`META-INF/services/`目录下定义接口实现类文件,Java程序可利用`ServiceLoader`动态加载服务实现。SPI核心思想是解耦,允许不同厂商为同一接口提供多种实现,如`java.sql.Driver`的MySQL与PostgreSQL实现。然而,SPI存在缺陷:需遍历所有实现并实例化,可能造成资源浪费;获取实现类方式不够灵活;多线程使用时存在安全问题。尽管如此,SPI仍是Java生态系统中实现插件化和模块化设计的重要工具。
144 0
|
2月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
149 4
|
3月前
|
Java 数据挖掘 调度
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
193 5
|
3月前
|
监控 搜索推荐 Java
Java 多线程最新实操技术与应用场景全解析:从基础到进阶
本文深入探讨了Java多线程的现代并发编程技术,涵盖Java 8+新特性,如CompletableFuture异步处理、Stream并行流操作,以及Reactive编程中的Reactor框架。通过具体代码示例,讲解了异步任务组合、并行流优化及响应式编程的核心概念(Flux与Mono)。同时对比了同步、CompletableFuture和Reactor三种实现方式的性能,并总结了最佳实践,帮助开发者构建高效、扩展性强的应用。资源地址:[点击下载](https://pan.quark.cn/s/14fcf913bae6)。
223 3
|
4月前
|
算法 Java 调度
Java多线程基础
本文主要讲解多线程相关知识,分为两部分。第一部分涵盖多线程概念(并发与并行、进程与线程)、Java程序运行原理(JVM启动多线程特性)、实现多线程的两种方式(继承Thread类与实现Runnable接口)及其区别。第二部分涉及线程同步(同步锁的应用场景与代码示例)及线程间通信(wait()与notify()方法的使用)。通过多个Demo代码实例,深入浅出地解析多线程的核心知识点,帮助读者掌握其实现与应用技巧。
|
4月前
|
Java
java 多线程异常处理
本文介绍了Java中ThreadGroup的异常处理机制,重点讲解UncaughtExceptionHandler的使用。通过示例代码展示了当线程的run()方法抛出未捕获异常时,JVM如何依次查找并调用线程的异常处理器、线程组的uncaughtException方法或默认异常处理器。文章还提供了具体代码和输出结果,帮助理解不同处理器的优先级与执行逻辑。
118 1
|
4月前
|
人工智能 JavaScript Java
Java反射机制及原理
本文介绍了Java反射机制的基本概念、使用方法及其原理。反射在实际项目中比代理更常用,掌握它可以提升编程能力并理解框架设计原理。文章详细讲解了获取Class对象的四种方式:对象.getClass()、类.class、Class.forName()和类加载器.loadClass(),并分析了Class.forName()与ClassLoader的区别。此外,还探讨了通过Class对象进行实例化、获取方法和字段等操作的具体实现。最后从JVM类加载机制角度解析了Class对象的本质及其与类和实例的关系,帮助读者深入理解Java反射的工作原理。
|
2月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。