当前位置: 代码迷 >> Java相关 >> 黑马软件工程师系列第二篇 多线程(2)
  详细解决方案

黑马软件工程师系列第二篇 多线程(2)

热度:62   发布时间:2016-04-22 19:31:08.0
黑马程序员系列第二篇 多线程(2)

 ASP.Net+Android+IOS开发  、Net培训、期待与您交流!

 

(前言:本篇文章主要依据毕向东老师的课程视频整理而成,如要详细学习,请观看毕老师视频  百度网盘链接地址:http://pan.baidu.com/s/1sjQRHDz)

 

目录:1、线程通信--生产消费者示例(线程通信安全、等待唤醒机制)    2、停止线程、及其会出现的问题、及解决的办法    3、守护线程及几个Thread的方法                   4、工作中线程的常见写法

        1、线程通信--生产消费者示例

代码示例:

 1 public class ProducerConsumer { 2 //需求:生产和消费行为依次进行。     设置产品为BMW   设置生产者和消费者线程各两个 3     public static void main(String[] args) { 4          5          Product pro=new Product(); 6           7         new Thread(new Producter(pro)).start();        8         new Thread(new Consumer(pro)).start(); 9         new Thread(new Producter(pro)).start();10         new Thread(new Consumer(pro)).start();11 12     }13 }14 class Product{15     16     private String name;17     private int No=1;18     boolean flag=false;19     20     public synchronized void set(String names){21         while(flag)22             try {23                  this.wait();//等待状态                24             } catch (InterruptedException e) {25                 e.printStackTrace();26             }    27               this.name=names+"---"+this.No++;28               System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生产");            29                 flag=true;30                 this.notifyAll();//唤醒所有线程31     }    32     public synchronized void out(){33         while(!flag)34             try {35                 this.wait();//等待状态36             } catch (InterruptedException e) {37                 e.printStackTrace();38             }        39         System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消费了-------");        40                flag=false;41                this.notifyAll();//唤醒所有线程42     }43 }44 //生产者45 class Producter implements Runnable{46     private Product p;47     public Producter(Product pr){48         this.p=pr;49     }50     public void run(){        51       while(true){52         p.set("BMW");53       }54     }    55 }56 //消费者57 class Consumer implements Runnable{58     private Product p;59     public Consumer(Product pr){60         this.p=pr;61     }    62     public void run(){        63         while(true){64         p.out();65         }66     }67 }

 

使用JDK5.0新特性改进后的代码

 1 /*JDK5.0后增加了Lock 和Condition新类特性来取代 同步和锁的繁琐操作 */ 2 public class ProducerConsumerNew { 3  4     public static void main(String[] args) { 5          6         Product pro=new Product(); 7          8        new Thread(new Producter(pro)).start();        9        new Thread(new Consumer(pro)).start();10        new Thread(new Producter(pro)).start();11        new Thread(new Consumer(pro)).start();12          13     }14 15 }16 class ProductNew{    17     private String name;18     private int No=1;19     boolean flag=false;20     21     private Lock lock=new ReentrantLock();22     private Condition con1=lock.newCondition();23     private Condition con2=lock.newCondition();24     25     public  void set(String name){26         27         while(flag)28             try {29                 lock.lock();30                 con1.wait();31             } catch (InterruptedException e) {32                 e.printStackTrace();33             }finally{34                 lock.unlock();35             }36           this.name=name+"---"+this.No++;  37           System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生产");38             39           this.flag=true;40           con2.signal();41     }42     43     public  void out(){        44         while(!this.flag)45             try {46                 lock.lock();47                 con2.wait();48             } catch (InterruptedException e) {49                 e.printStackTrace();50             }finally{51                 lock.unlock();52                 con1.signal();53             }        54         System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消费了-------");55         56         this.flag=false;57     }58 }59 //生产者60 class ProducterNew implements Runnable{61     private ProductNew p;62     public ProducterNew(ProductNew pr){63         this.p=pr;64     }65     public void run(){66       while(true){67         p.set("BMW");68       }69     }    70 }71 //消费者72 class ConsumerNew implements Runnable{73     private ProductNew p;74     public ConsumerNew(ProductNew pr){75         this.p=pr;76     }    77     public void run(){78         while(true)79         p.out();80     }81 }    

  

2、停止线程、及其会出现的问题、及解决的办法    

停止线程思路:开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run()方法结束,线程即结束。

特殊情况:当线程处于冻结状态(wait()),就不会读取到标记,那么线程就不会结束。

解决办法:当没有指定的方式让冻结的线程恢复到运行状态时,需要用Interrupt()方法强制清除冻结状态,再用操作标记让线程结束 

 

一个简单的代码例子

 1 public class ThreadStop { 2  3     public static void main(String[] args) { 4          5         ThreadTt tt=new ThreadTt(); 6          7         Thread th1=new Thread(tt); 8         Thread th2=new Thread(tt); 9         th1.start();10         th2.start();11         int count=0;12         while(true){13             if(++count>60){     //循环来控制线程的结束14                 th1.interrupt();  //强制清除线程冻结状态15                 th2.interrupt();16                 break;17             }18             System.out.println(Thread.currentThread().getName()+"....run---"+count);19         }      20         System.out.println(Thread.currentThread().getName()+"....over");21     }22 }23 class ThreadTt implements Runnable{24     25    boolean flag=true;26    Lock lock=new ReentrantLock();27    Condition con=lock.newCondition();28     public synchronized void run() {29         30         while(flag){31             try {32                 wait();       //用这个方法让线程处于冻结状态33             } catch (InterruptedException e) {34                 System.out.println(e.getStackTrace());35                  flag=false;36             }37         System.out.println(Thread.currentThread().getName()+"...run");38         }39     }40 }

 

 

3、守护线程及几个Thread的方法

 

守护线程/用户线程:通俗而言为”后台进程”,当前台进程都结束时,后台进程自动结束;当正在运行的线程都是守护线程时,JVM自动退出。     

 

setDaemon()方法设置守护线程,该方法必须在启动线程前调用

 

 

Join()方法  特点:当A线程执行到了B线程的jion()方法是,A就会等待,等B线程都执行完以后,A才会执行。Jion可以用来临时加入线程执行    线程抢夺cpu执行权

 

ToString()方法

 

setPriority()方法 更改线程的优先级,优先级代表抢夺资源的频率高低

 

Yield()方法  暂停当前线程的执行,去执行其它线程

 

4、工作中线程的常见写法(用到内部类)

不多说,看代码

 1 public class ThreadStand { 2  3     public static void main(String[] args) { 4      //工作中多线程的常见写法,构建内部类 5         new Thread(){ 6             public void run(){ 7                 for(int i=0;i<100;i++) 8                     System.out.println(Thread.currentThread().getName()+"....run...."+i); 9             }10         }.start();11         12         for(int i=0;i<100;i++)13             System.out.println(Thread.currentThread().getName()+"....run...."+i);14         15         //构造内部类16         Runnable rn= new Runnable(){17             public void run() {18                 for(int i=0;i<100;i++)19                     System.out.println(Thread.currentThread().getName()+"....run...."+i);                20             }21         };  22         new Thread(rn).start();   23     }24 }

       

       初学者难免错误,欢迎评判指教,持续更正ing...........

 

ASP.Net+Android+IOS开发  、Net培训、期待与您交流!

 

  相关解决方案