黑马程序员系列第二篇 多线程(2)

 

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

 

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

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

代码示例:

public class ProducerConsumer {
//需求:生产和消费行为依次进行。     设置产品为BMW   设置生产者和消费者线程各两个
    public static void main(String[] args) {
        
         Product pro=new Product();
         
        new Thread(new Producter(pro)).start();       
        new Thread(new Consumer(pro)).start();
        new Thread(new Producter(pro)).start();
        new Thread(new Consumer(pro)).start();

    }
}
class Product{
    
    private String name;
    private int No=1;
    boolean flag=false;
    
    public synchronized void set(String names){
        while(flag)
            try {
                 this.wait();//等待状态                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    
              this.name=names+"---"+this.No++;
              System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生产");            
                flag=true;
                this.notifyAll();//唤醒所有线程
    }    
    public synchronized void out(){
        while(!flag)
            try {
                this.wait();//等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }        
        System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消费了-------");        
               flag=false;
               this.notifyAll();//唤醒所有线程
    }
}
//生产者
class Producter implements Runnable{
    private Product p;
    public Producter(Product pr){
        this.p=pr;
    }
    public void run(){        
      while(true){
        p.set("BMW");
      }
    }    
}
//消费者
class Consumer implements Runnable{
    private Product p;
    public Consumer(Product pr){
        this.p=pr;
    }    
    public void run(){        
        while(true){
        p.out();
        }
    }
}

 

 

 

使用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...........

 

 

posted @ 2015-11-10 22:10  YerJustDoIt  阅读(303)  评论(0编辑  收藏  举报