java多线程的同步 通信以及生产消费者问题

本文涉及的产品
文本翻译,文本翻译 100万字符
图片翻译,图片翻译 100张
文档翻译,文档翻译 1千页
简介: Demo1 /*   Runable接口比直接从Thread继承方便的多  。  *    new  Thread(...) ;这样即使我们传递了同一个实现了Runnable接口的多个对象那么 也是多个线程 ,而且多个线程共享数据域.

Demo1

/*   Runable接口比直接从Thread继承方便的多  。 
*    new  Thread(...) ;这样即使我们传递了同一个实现了Runnable接口的多个对象那么 也是多个线程 ,而且多个线程共享数据域.
*    否则new Thread 创建的多个线程之间 互不相干  ,数据之间互不干涉
*    同步就是为了实现 在多个线程同时对一个资源进行操作的时候 要一个一个的执行 ,
*    只有等占有CPU的 线程完事之后 其他等待线程才能进入就绪状态等待运行
*    java中可以用 synchrozined(Object obj){}      实现代码块的同步      参数是任意对象 
*    不但可以利用synchronized语句块  也可以在方法的前面 声明 synchronized      
*    同步原理是对象的标志位 初始为1  当进入代码块后 obj的标志位变为 0  这时候其他线程则不能 进入代码块执行 而进入等待状态
*    直到先进入的那个线程完事然后就会为这个线程解锁 。 其他线程才可能开始运行   火车票的售票系统就是一个多线程很好的运用的例子
*    同步是以程序的性能为代价的   ,同步方法是以类的this对象为同步对象的  而 synchronized块是以我们指定的对象为 同步对象
*    如果想让代码块和同步方法同步那么 使用的同步对象 必须都为this
*/  
public class  ThreadDemo2
{
   public static void main(String []args)
   {
       MyThread mt=new MyThread() ;  
       //mt.start() ;
       new Thread(mt) .start() ;
       try
      {
       Thread.sleep(10) ; //每当产生一个线程CPU不会立马去执行 ,这之间既有一个微小的时间间隔 。
      }
      catch(Exception e)
      {
       System.out.println(e.toString()) ;
      }
       mt.str="method";
       new Thread(mt) .start() ;
   }
}
class  MyThread    implements Runnable// extends   Thread
{  
   int tickets=100 ;
   String str=new String("");
   public void run()
   {
       if(str.equals("method"))
       {
        while(true)
        {
         running() ;
        }
       }
       else
       {
        while(true)
        {
         synchronized(str)
        {
         if(tickets>0 )
         {
          System.out.println("block:"+Thread.currentThread().getName()+"sells"+tickets--);
         }
        }
         
        }
       }
   }
   public  synchronized  void running()
   {    
      if(tickets>0) 
       {
        try{Thread.sleep(10);}catch(Exception ex){}
        System.out.print("method:") ;
        System.out.println(Thread.currentThread() +"sell " + tickets-- ) ;
       }
   }
}  

 

Demo2:

/*
*   java多线程中 有前台线程和后台线程,前台线程 是指 main所在的主线程 和其他 创建的线程 ,如果在线程调用start 之前调用  setDeamon(true)
*   那么 这个线程就是一个后台线程,在进程中如果没有一个前台线程 那么后台线程也随之退出,从而进程也退出 。如果没有调用setDeamon(true)或者
*   调用setDeamom(false)那么这个线程就是前台线程 ,只要一个进程中还存在前台线程 那么即使mian方法所在的线程退出了 ,那么这个前台子线程也会继续执行
*   直至退出  。
*   Tread类额join方法 是将一个线程合并到另一个线程中, 可以设置合并的时间间隔
*   我们实现自己的线程类有2中方法  :
*   1、直接从Thread继承而来  实现 run方法  。
*   2、实现Runnable接口,并且实现run方法 。 Thread  th=new Thread(....) ;//吧我们自己实现的类的对象作为参数传进去   .
*   join 方法可以将一个线程合并到另一个线程 中 而且还可以指定线程合并的时间间隔
*
*/
public  class  ThreadDemo1
{
      public static  void main(String[]args) 
      {
        //MyThread tt=new MyThread() ; tt.start() ;可以从 Thread类派生一个线程类
        Thread tt=new Thread(new MyThread()) ;  //可以通过Thread类的带参数的构造方法 传递一个实现了Runnable接口的对象
   //     tt.setDaemon(true) ;//将线程设置为 后台线程  主线层退出这个线程也会随着退出 
        tt.start() ;
        int index=0 ;
        while(true)
        {
         if(index++==100)
         try{
           tt.join(5000) ;
         }
         catch(Exception ex)
        {
         System.out.println(ex.toString()) ;
        }
          
         System.out.println("run:"+Thread.currentThread().getName()) ;
        }
      }

}
class  MyThread  implements Runnable//extends    Thread
{
    public void run()
    {
      while(true)
      {
      System.out.println("run:"+Thread.currentThread().getName()) ;
      }
    }
}

Demo3:

/*   线程之间的通信是协调线程同步的重要方法   、
*    Object类的 wait方法通告同步对象进入等待状态,直到其他线程得到同步对象 并且调用 notity方法 ,等待线程才会继续执行
*    notify方法 是通告同步对象的等待线程进入恢复运行 
*    notifyAll通告所有堵塞线程恢复运行
*     下面是一个生产消费者的问题   ,在对于类的操作的时候 一定要有面向对象的思想  。  否则 就会非常的杂乱
*/
class  Producer  implements  Runnable
{
 Q q  ;
 public Producer(Q q)
 {
  this.q=q ;
 }
 public  void run()
 { 
    int i=0 ;
    while(true)
    {
    /* synchronized(q)
     {
      if(q.bFull==true)
          try{q.wait() ;}catch(Exception ex){}
         if(i==0)
     {
       q.name="zhangsan" ;
       try{
       Thread.sleep(1) ;
      }catch(Exception ex){}
       q.sex="male"  ;
     }
     else
     {
      q.name="lisi"  ;
      q.sex="female" ;
     }  
     q.bFull=true ;
     q.notify() ;
    }
     i=(i+1)%2 ;
     */ 
   
     if(i==0 )
      q.push("zhangsan","male");
       else
      q.push("lisi","female") ;  
      i=(i+1)%2 ;
    }
      
 }
}
class Consumer implements  Runnable 
{  
   Q q ;
   public Consumer(Q q)
   {
    this.q=q ;
   }
   public   void  run()
   {
      while(true)
     {
     /*  synchronized(q)
       {
         if(!q.bFull)
         {
        try{q.wait() ;}catch(Exception ex){}
          }
          System.out.println(q.name+":"+q.sex) ;
          q.bFull=false ;
           q.notify() ;
        }
      */
      q.get() ;
     }
   }
}

class  Q   //以面向对象的思想对线程之间的通信进行封装从而实现消费者 生产社的问题
{
 String name="unknown"  ;
 String sex ="unknown"  ;
 boolean bFull=false ;
 public synchronized void push(String name,String sex)
 {     
      if(this.bFull==true)
               try{wait() ;}catch(Exception ex){}
       this.name=name ;
       this.sex=sex   ; 
       bFull=true ;
       try{notify() ;}catch(Exception ex){}
 }
 public synchronized void get()
 {
  if(this.bFull==false)
     try{wait() ;}catch(Exception ex){}
  System.out.println("name:"+this.name+" sex:"+this.sex) ;
     bFull=false ;
     try{notify() ;}catch(Exception ex){}
 }
}


class  ThreadTest  implements  Runnable    //这个线程类 来模拟线程的声明结束  因为Thread类的 stop suspend等方法都已经过时了
{                                          //所以有时候我们对于线程的开始和结束要自己设置标志位来
  boolean bRun=true ;
  int index=0 ;
  public  void  stopMe()
  {
   bRun=false ;
  }
  public  void run()
  {
   while(bRun)
   { 
      if(++index>100)
        stopMe() ;
     System.out.println(Thread.currentThread().getName()+" is running!");
   }
  
   }
 
}

public  class  ThreadDemo3
{
  
   public static void main(String[]args)
   {
    
   Q q=new Q() ;
    new Thread(new Producer(q)).start() ;
   new Thread(new Consumer(q)).start() ; 
 
   }
}

 

目录
相关文章
|
9天前
|
Java 数据库
【YashanDB知识库】kettle同步大表提示java内存溢出
在数据导入导出场景中,使用Kettle进行大表数据同步时出现“ERROR:could not create the java virtual machine!”问题,原因为Java内存溢出。解决方法包括:1) 编辑Spoon.bat增大JVM堆内存至2GB;2) 优化Kettle转换流程,如调整批量大小、精简步骤;3) 合理设置并行线程数(PARALLELISM参数)。此问题影响所有版本,需根据实际需求调整相关参数以避免内存不足。
|
1月前
|
安全 Java 开发者
Java并发迷宫:同步的魔法与死锁的诅咒
在Java并发编程中,合理使用同步机制可以确保线程安全,避免数据不一致的问题。然而,必须警惕死锁的出现,采取适当的预防措施。通过理解同步的原理和死锁的成因,并应用有效的设计和编码实践,可以构建出高效、健壮的多线程应用程序。
47 21
|
1月前
|
Java Shell 数据库
【YashanDB 知识库】kettle 同步大表提示 java 内存溢出
【问题分类】数据导入导出 【关键字】数据同步,kettle,数据迁移,java 内存溢出 【问题描述】kettle 同步大表提示 ERROR:could not create the java virtual machine! 【问题原因分析】java 内存溢出 【解决/规避方法】 ①增加 JVM 的堆内存大小。编辑 Spoon.bat,增加堆大小到 2GB,如: if "%PENTAHO_DI_JAVA_OPTIONS%"=="" set PENTAHO_DI_JAVA_OPTIONS="-Xms512m" "-Xmx512m" "-XX:MaxPermSize=256m" "-
|
3月前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
4月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
5月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
54 1
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
56 17
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
62 26
|
3月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
314 2
|
4月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####