黑马程序员_Java基础_多线程2

一、多线程(线程间通信-示例代码)

[java]  view plain copy
  1. /* 
  2. 线程间通讯: 
  3. 其实就是多个线程在操作同一个资源,但是操作的动作不同。 
  4. */  
  5. class Res  
  6. {  
  7.     String name;  
  8.     String sex;  
  9. }  
  10. class Input implements Runnable  
  11. {  
  12.     private Res r;  
  13.     Input(Res r)  
  14.     {  
  15.         this.r=r;  
  16.     }  
  17.     public void run()  
  18.     {  
  19.         int x=0;  
  20.         while(true)  
  21.         {  
  22.             if(x==0)  
  23.             {  
  24.                 r.name="mike";  
  25.                 r.sex="男";  
  26.             }  
  27.             else  
  28.             {  
  29.                 r.name="lili";  
  30.                 r.sex="女";  
  31.             }  
  32.             x=(x+1)%2;        
  33.         }  
  34.     }  
  35. }  
  36. class Output implements Runnable  
  37. {  
  38.     private Res r;  
  39.     Output(Res r)  
  40.     {  
  41.         this.r=r;  
  42.     }  
  43.     public void run()  
  44.     {  
  45.         while(true)  
  46.         {  
  47.             System.out.println("姓名:"+r.name+"\t"+"性别:"+r.sex);  
  48.         }  
  49.     }  
  50. }  
  51. class InputOutputDemo   
  52. {  
  53.     public static void main(String[] args)   
  54.     {  
  55.         Res r=new Res();  
  56.         Input in=new Input(r);  
  57.         Output out=new Output(r);  
  58.   
  59.         Thread t1=new Thread(in);  
  60.         Thread t2=new Thread(out);  
  61.         t1.start();  
  62.         t2.start();  
  63.     }  
  64. }  


二、多线程(线程间通信-解决安全问题)

[java]  view plain copy
  1. /* 
  2. 线程间通讯: 
  3. 其实就是多个线程在操作同一个资源,但是操作的动作不同。 
  4. */  
  5. class Res  
  6. {  
  7.     String name;  
  8.     String sex;  
  9. }  
  10. class Input implements Runnable  
  11. {  
  12.     private Res r;  
  13.     Input(Res r)  
  14.     {  
  15.         this.r=r;  
  16.     }  
  17.     public void run()  
  18.     {  
  19.         int x=0;  
  20.         while(true)  
  21.         {  
  22.             synchronized(r)//Input.class也可以  
  23.             {  
  24.                 if(x==0)  
  25.                 {  
  26.                     r.name="mike";  
  27.                     r.sex="男";  
  28.                 }  
  29.                 else  
  30.                 {  
  31.                     r.name="lili";  
  32.                     r.sex="女";  
  33.                 }  
  34.                 x=(x+1)%2;  
  35.             }  
  36.         }  
  37.     }  
  38. }  
  39. class Output implements Runnable  
  40. {  
  41.     private Res r;  
  42.     Output(Res r)  
  43.     {  
  44.         this.r=r;  
  45.     }  
  46.     public void run()  
  47.     {  
  48.         while(true)  
  49.         {  
  50.             synchronized(r)  
  51.             {  
  52.                 System.out.println("姓名:"+r.name+"\t"+"性别:"+r.sex);  
  53.             }  
  54.         }  
  55.     }  
  56. }  
  57. class InputOutputDemo   
  58. {  
  59.     public static void main(String[] args)   
  60.     {  
  61.         Res r=new Res();  
  62.         Input in=new Input(r);  
  63.         Output out=new Output(r);  
  64.   
  65.         Thread t1=new Thread(in);  
  66.         Thread t2=new Thread(out);  
  67.         t1.start();  
  68.         t2.start();  
  69.     }  
  70. }  


三、多线程(线程间通信-等待唤醒机制)

wait():

notify():

notifyAll():

都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法要定义在Object类中呢?

因为这些方法在操作同步中线程时,都必须要表示它们所操作线程只有的锁,只有同一个锁上的被等待线程,才可以被同一个上notify唤醒。也就是说等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

[java]  view plain copy
  1. /* 
  2. 线程间通讯: 
  3. 其实就是多个线程在操作同一个资源,但是操作的动作不同。 
  4. */  
  5. class Res  
  6. {  
  7.     String name;  
  8.     String sex;  
  9.     boolean flag=false;  
  10. }  
  11. class Input implements Runnable  
  12. {  
  13.     private Res r;  
  14.     Input(Res r)  
  15.     {  
  16.         this.r=r;  
  17.     }  
  18.     public void run()  
  19.     {  
  20.         int x=0;  
  21.         while(true)  
  22.         {  
  23.             if(r.flag)  
  24.                 try{r.wait();}catch(Exception e){}//存入线程池中  
  25.             synchronized(r)//Input.class也可以  
  26.             {  
  27.                 if(x==0)  
  28.                 {  
  29.                     r.name="mike";  
  30.                     r.sex="男";  
  31.                 }  
  32.                 else  
  33.                 {  
  34.                     r.name="lili";  
  35.                     r.sex="女";  
  36.                 }  
  37.                 x=(x+1)%2;  
  38.   
  39.                 r.flag=true;  
  40.                 r.notify();//唤醒线程池中的线程。(第一个存放的,例如队列)  
  41.             }  
  42.         }  
  43.     }  
  44. }  
  45. class Output implements Runnable  
  46. {  
  47.     private Res r;  
  48.     Output(Res r)  
  49.     {  
  50.         this.r=r;  
  51.     }  
  52.     public void run()  
  53.     {  
  54.         while(true)  
  55.         {  
  56.             synchronized(r)  
  57.             {  
  58.                 if(!r.flag)  
  59.                     try{r.wait();}catch(Exception e){}//存入线程池中  
  60.                   
  61.                 System.out.println("姓名:"+r.name+"\t"+"性别:"+r.sex);  
  62.   
  63.                 r.flag=false;  
  64.                 r.notify();//唤醒线程池中的线程。(第一个存放的,例如队列)  
  65.             }  
  66.         }  
  67.     }  
  68. }  
  69. class InputOutputDemo   
  70. {  
  71.     public static void main(String[] args)   
  72.     {  
  73.         Res r=new Res();  
  74.         Input in=new Input(r);  
  75.         Output out=new Output(r);  
  76.   
  77.         Thread t1=new Thread(in);  
  78.         Thread t2=new Thread(out);  
  79.         t1.start();  
  80.         t2.start();  
  81.     }  
  82. }  


四、多线程(线程间通信-代码优化)

[java]  view plain copy
  1. /* 
  2. 优化: 
  3. */  
  4. class Res  
  5. {  
  6.     private String name;  
  7.     private String sex;  
  8.     private boolean flag=false;  
  9.   
  10.     public synchronized void set(String name,String sex)  
  11.     {  
  12.         if(flag)  
  13.             try{this.wait();}catch(Exception e){}//存入线程池中  
  14.   
  15.         this.name=name;  
  16.         this.sex=sex;  
  17.           
  18.         flag=true;  
  19.         this.notify();  
  20.           
  21.     }  
  22.     public synchronized void out()  
  23.     {  
  24.         if(!flag)  
  25.             try{this.wait();}catch(Exception e){}//存入线程池中  
  26.   
  27.         System.out.println("姓名:"+this.name+"\t"+"性别:"+this.sex);  
  28.   
  29.         flag=false;  
  30.         this.notify();//唤醒线程池中的线程。(第一个存放的,例如队列)  
  31.   
  32.   
  33.     }  
  34. }  
  35. class Input implements Runnable  
  36. {  
  37.     private Res r;  
  38.     Input(Res r)  
  39.     {  
  40.         this.r=r;  
  41.     }  
  42.     public void run()  
  43.     {  
  44.         int x=0;  
  45.         while(true)  
  46.         {  
  47.             if(x==0)  
  48.             {  
  49.                 r.set("maike","男");  
  50.                       
  51.             }  
  52.             else  
  53.             {  
  54.                 r.set("lili","女");  
  55.             }  
  56.             x=(x+1)%2;  
  57.         }  
  58.     }  
  59. }  
  60. class Output implements Runnable  
  61. {  
  62.     private Res r;  
  63.     Output(Res r)  
  64.     {  
  65.         this.r=r;  
  66.     }  
  67.     public void run()  
  68.     {  
  69.         while(true)  
  70.         {  
  71.             r.out();  
  72.         }  
  73.     }  
  74. }  
  75. class InputOutputDemo   
  76. {  
  77.     public static void main(String[] args)   
  78.     {   Res r=new Res();  
  79.         new Thread(new Input(r)).start();  
  80.         new Thread(new Output(r)).start();  
  81.     }  
  82. }  


五、多线程(线程间通信-生产者消费者)

[java]  view plain copy
  1. /* 
  2. 生产者消费者: 
  3. */  
  4. class ProducerConsumerDemo   
  5. {  
  6.     public static void main(String[] args)   
  7.     {  
  8.         Resource r=new Resource();  
  9.   
  10.         Producer pro=new Producer(r);  
  11.         Consumer con=new Consumer(r);  
  12.   
  13.         Thread t1=new Thread(pro);  
  14.         Thread t2=new Thread(con);  
  15.   
  16.         t1.start();  
  17.         t2.start();  
  18.     }  
  19. }  
  20.   
  21. class Resource  
  22. {  
  23.     private String name;  
  24.     private int count=1;  
  25.     private boolean flag=false;  
  26.   
  27.     public synchronized void set(String name)  
  28.     {  
  29.         while(flag)  
  30.             try{this.wait();}catch(Exception e){}  
  31.         this.name=name+"--"+count++;  
  32.   
  33.         System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);  
  34.           
  35.         flag=true;  
  36.         this.notifyAll();  
  37.     }  
  38.     public synchronized void out()  
  39.     {  
  40.         while(!flag)  
  41.             try{this.wait();}catch(Exception e){}  
  42.         System.out.println(Thread.currentThread().getName()+"...消费者..........."+this.name);  
  43.           
  44.         flag=false;  
  45.         this.notifyAll();  
  46.     }  
  47. }  
  48.   
  49. class Producer implements Runnable  
  50. {  
  51.     private Resource res;  
  52.   
  53.     Producer(Resource res)  
  54.     {  
  55.         this.res=res;  
  56.     }  
  57.     public void run()  
  58.     {  
  59.         while(true)  
  60.         {  
  61.             res.set("+商品+");  
  62.         }  
  63.     }  
  64. }  
  65. class Consumer implements Runnable  
  66. {  
  67.     private Resource res;  
  68.   
  69.     Consumer(Resource res)  
  70.     {  
  71.         this.res=res;  
  72.     }  
  73.     public void run()  
  74.     {  
  75.         while(true)  
  76.         {  
  77.             res.out();  
  78.         }  
  79.     }  
  80.   
  81. }  


说明:

对于多个生产者和消费者,为什么要定义while判断标记?

原因:让被唤醒的线程再一次判断标记。

为什么定义notityAll ?

因为需要唤醒对方线程,只用notify容易唤醒本方线程的情况,导致程序中的所有线程都等待。

六、多线程(线程间通信-生产者消费者JDK5.0升级版)

[java]  view plain copy
  1. /* 
  2. JDK1.5中提供了多线程升级解决方案。(显式锁机制) 
  3. 将同步Synchronized替换成实现Lock操作。 
  4. 将Object中的wait,notify,notifyAll替换成Condition对象。 
  5. 该对象可以通过Lock锁的newCondition()进行获取。 
  6.  
  7. 在该示例中,实现了本方只唤醒对方的操作。 
  8.  
  9. */  
  10.   
  11. import java.util.concurrent.locks.*;  
  12. class ProducerConsumerDemo   
  13. {  
  14.     public static void main(String[] args)   
  15.     {  
  16.         Resource r=new Resource();  
  17.   
  18.         Producer pro=new Producer(r);  
  19.         Consumer con=new Consumer(r);  
  20.   
  21.         Thread t1=new Thread(pro);  
  22.         Thread t2=new Thread(con);  
  23.         Thread t3=new Thread(pro);  
  24.         Thread t4=new Thread(con);  
  25.   
  26.         t1.start();  
  27.         t2.start();  
  28.         t3.start();  
  29.         t4.start();  
  30.     }  
  31. }  
  32.   
  33.   
  34. class Resource  
  35. {  
  36.     private String name;  
  37.     private int count=1;  
  38.     private boolean flag=false;  
  39.   
  40.     private Lock lock=new ReentrantLock();  
  41.     private Condition condition_pro=lock.newCondition();//生产  
  42.     private Condition condition_con=lock.newCondition();//消费  
  43.   
  44.     public  void set(String name)throws InterruptedException  
  45.     {  
  46.         lock.lock();//加锁  
  47.         try  
  48.         {  
  49.             while(flag)  
  50.                 condition_pro.await();//挂起线程  
  51.   
  52.             this.name=name+"--"+count++;  
  53.   
  54.             System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);  
  55.           
  56.             flag=true;  
  57.           
  58.             condition_con.signal();//唤醒线程  
  59.         }  
  60.         finally  
  61.         {  
  62.             lock.unlock();//释放锁的动作一定要执行。  
  63.         }     
  64.     }  
  65.     public  void out()throws InterruptedException  
  66.     {  
  67.         lock.lock();  
  68.         try  
  69.         {  
  70.             while(!flag)  
  71.                 condition_con.await();  
  72.   
  73.             System.out.println(Thread.currentThread().getName()+"...消费者..........."+this.name);  
  74.           
  75.             flag=false;  
  76.             condition_pro.signal();  
  77.         }  
  78.         finally  
  79.         {  
  80.             lock.unlock();  
  81.         }  
  82.     }  
  83. }  
  84.   
  85. class Producer implements Runnable  
  86. {  
  87.     private Resource res;  
  88.   
  89.     Producer(Resource res)  
  90.     {  
  91.         this.res=res;  
  92.     }  
  93.     public void run()  
  94.     {  
  95.         while(true)  
  96.         {  
  97.             try  
  98.             {  
  99.                 res.set("+商品+");  
  100.             }  
  101.             catch (InterruptedException e)  
  102.             {  
  103.             }  
  104.               
  105.         }  
  106.     }  
  107. }  
  108. class Consumer implements Runnable  
  109. {  
  110.     private Resource res;  
  111.   
  112.     Consumer(Resource res)  
  113.     {  
  114.         this.res=res;  
  115.     }  
  116.     public void run()  
  117.     {  
  118.         while(true)  
  119.         {  
  120.             try  
  121.             {  
  122.                 res.out();  
  123.             }  
  124.             catch (InterruptedException e)  
  125.             {  
  126.             }  
  127.               
  128.         }  
  129.     }  
  130.   
  131. }  


七、多线程(停止线程)

[java]  view plain copy
  1. /* 
  2. stop 方法已经过时,如何停止进程? 
  3. 只有一种,run方法结束。 
  4. 开启多线程运行,运行代码通常都是循环结构,只要控制住循环,就可以 
  5. 让run方法结束,也就是线程结束。 
  6.  
  7.  
  8. 特殊情况: 
  9. 当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。 
  10.  
  11. 当没有指定的方式让冻结的线程恢复到运行状态时,这时就需要对冻结进行清除, 
  12. 强制让线程回复到运行状态中来,这样就可以操作标记,让线程结束。 
  13. Thread类中提供了该方法interrupt(); 
  14.  
  15. */  
  16. class StopThread implements Runnable  
  17. {  
  18.     private boolean flag=true;  
  19.   
  20.     public synchronized void run()  
  21.     {  
  22.         while(flag)  
  23.         {  
  24.             try  
  25.             {  
  26.                 this.wait();  
  27.             }  
  28.             catch (InterruptedException e)  
  29.             {  
  30.                 System.out.println(Thread.currentThread().getName()+"....Exception");  
  31.                 flag=false;  
  32.             }  
  33.             System.out.println(Thread.currentThread().getName()+"....run");  
  34.         }  
  35.     }  
  36.     public void changeFlag()  
  37.     {  
  38.         flag=false;  
  39.     }  
  40. }  
  41. class StopThreadDemo   
  42. {  
  43.     public static void main(String[] args)   
  44.     {  
  45.         StopThread st=new StopThread();  
  46.         Thread t1=new Thread(st);  
  47.         Thread t2=new Thread(st);  
  48.   
  49.         t1.start();  
  50.         t2.start();  
  51.   
  52.         int num=0;  
  53.   
  54.         while(true)  
  55.         {  
  56.             if(num++==60)  
  57.             {  
  58.                 //st.changeFlag();  
  59.                 t1.interrupt();  
  60.                 t2.interrupt();  
  61.                 break;  
  62.             }  
  63.             System.out.println(Thread.currentThread().getName()+"....."+num);  
  64.         }  
  65.         System.out.println("结束");  
  66.     }  
  67. }  


八、多线程(守护线程)

public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。 

该方法必须在启动线程前调用。 

该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。 

参数:

on - 如果为 true,则将该线程标记为守护线程。 

一句话总结:守护线程类似于保镖,“保护”其它非守护线程,一旦非守护线程结束,这个“保镖”也就没有存在的意义,所以会守护线程在这时也会结束。

九、多线程(Join方法)

public final void join()

                throws InterruptedException

等待该线程终止。 

抛出: 

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

A线程执行到了B线程的join方法时,A线程就会等待B线程都执行完,A才会执行。

所以,join可以用来临时加入线程的执行。

[java]  view plain copy
  1. /* 
  2. join: 
  3. */  
  4. class Demo implements Runnable  
  5. {  
  6.     public void run()  
  7.     {  
  8.         for(int i=0;i<70;i++)  
  9.         {  
  10.             System.out.println(Thread.currentThread().getName()+"..."+i);  
  11.         }  
  12.     }  
  13. }  
  14. class  JoinDemo  
  15. {  
  16.     public static void main(String[] args) throws Exception  
  17.     {  
  18.         Demo d=new Demo();  
  19.         Thread t1=new Thread(d);  
  20.         Thread t2=new Thread(d);  
  21.         t1.start();  
  22.   
  23.         t1.join();  
  24.   
  25.         t2.start();  
  26.   
  27.         for(int i=0;i<80;i++)  
  28.         {  
  29.             System.out.println("main..."+i);  
  30.         }  
  31.         System.out.println("结束");  
  32.     }  
  33. }  


十、多线程(优先级和yield方法)

优先级:线程被执行的优先级别。

public final void setPriority(int newPriority)更改线程的优先级。 

首先调用线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException。 

在其他情况下,线程优先级被设定为指定的 newPriority 和该线程的线程组的最大允许优先级相比较小的一个。 

参数:

newPriority - 要为线程设定的优先级 

抛出: 

IllegalArgumentException - 如果优先级不在 MIN_PRIORITY 到 MAX_PRIORITY 范围内。 

SecurityException - 如果当前线程无法修改该线程。

yield方法:

public static void yield()暂停当前正在执行的线程对象,并执行其它线程。

 

 

[java]  view plain copy
  1. /* 
  2. 多线程的应用: 
  3. */  
  4. class ThreadTest   
  5. {  
  6.       
  7.     public static void main(String[] args)   
  8.     {  
  9.         new Thread()  
  10.         {  
  11.             public void run()  
  12.             {  
  13.                 for(int i=0;i<100;i++)  
  14.                 {  
  15.                     System.out.println(Thread.currentThread().getName()+"..."+i);  
  16.                 }  
  17.             }  
  18.         }.start();  
  19.           
  20.   
  21.         for(int i=0;i<100;i++)  
  22.         {  
  23.             System.out.println(Thread.currentThread().getName()+"..."+i);  
  24.         }  
  25.   
  26.           
  27.         new Thread(new Runnable()  
  28.         {  
  29.             public void run()  
  30.             {  
  31.                 for(int i=0;i<100;i++)  
  32.                 {  
  33.                     System.out.println(Thread.currentThread().getName()+"..."+i);  
  34.                 }     
  35.             }  
  36.         }).start();  
  37.           
  38.     }  
  39. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值