码迷,mamicode.com
首页 > 编程语言 > 详细

黑马程序员_多线程

时间:2014-08-22 00:04:35      阅读:314      评论:0      收藏:0      [点我收藏+]

标签:android   style   blog   http   color   java   使用   os   

 ------- android培训java培训、期待与您交流! ----------

                                        多线程
1、进程:
  正在运行的程序所占有的内存空间,叫做进程。
  线程:
  一个应用程序中的子程序,对于CPU,子程序可以有一条独立的执行路径,称为线程。
  线程特点:依靠一个应用程序,对于其他子程序,独立被CPU执行的
2、多线程的好处:
  充分利用CPU的资源,程序的同时运行,提高效率
3、java中线程创建的两种方法:
  第一种:
  定义类继承Thread class extends Thread
  重写Thread中的run方法;public void run()
  创建Thread类的子类对象
  调用子类对象的start方法,开启线程
注:start方法告诉JVM开启一个对CPU的执行路径,调用run方法。
  class A extends Thread {
    //..
    public void run() {
    // . . .
    }
  }
  A t = new A();
  t.start();

第二种(重点):
  定义类实现Runnable接口
  重写run方法
  创建Thread类对象
  调用Thread对象的start方法开启线程
  class A implements Runnable {

    public void run() {
    . . .
    }
  }
  Thread t=new Thread(new A());
  t.start();
  这两种方法的区别:
  第一种是继承,具有局限性,数据也是线程独享的;
  第二种是实现接口,避免了单继承的局限性,同时数据是线程共享的。
4、线程名字的获取和设置
  获取Thread子类的线程名字:
  Thread类的方法 String getName();
  获取非Thread子类的线程名字:
  Thread类的方法 static Thread currentThread();//返回当前正在执行的线程对象
  设置线程名字的方法:
  Thread类的方法 void setName(字符串的名字)
  利用Thread类的构造方法 Thread(字符串名字)
5、线程的状态图(重点)

  bubuko.com,布布扣
  冻结和阻塞的区别:
  冻结值线程的休眠或者等待,此时线程主动的放弃CPU的执行资格,同时也放弃了CPU的执行权力;
  阻塞时线程不会放弃CPU的执行资格,但没有CPU的执行权力。
6、同步机制,保证多线程在操作共享数据的安全性
  同步代码块:
  格式: synchronized(对象){
    线程操作的共享数据
  }
  对象:专业名词,对象监视器,锁
  同步方法:
  同步的非静态方法的锁是this,表示本类对象的引用
  同步的静态方法的锁是本类.class(因为JVM为每一种数据类型赋予了一个静态的成员变量,变量的返回值就是本类的class文件对象。)
7、多线程并发的单例模式懒汉(重点)
  懒汉,延迟加载,多线程并发实验,单例模式不能保证对象的唯一性。

 1 class single{
 2   private Single(){}
 3   private Single s=null;
 4 
 5   public static Single getInstance(){
 6     if(s==null){
 7       synchronized(Single.class){
 8         if(s==null)
 9           s=new Single()    
10       }    
11     }
12     return s;
13   }
14 }    

 


注:面试的时候,写同步代码块,不要写同步方法,进行两次判断提高程序的效率
8、死锁:(重点)
  多线程在争抢同一把锁的时候,造成的程序的假死现象。实际的开发中不可能出现

 1 class Dead implements Runnable{
 2   private boolean flag;
 3   Dead(){}
 4   Dead (boolean flag){this.flag=flag;}
 5   public void run(){
 6   while (true){
 7   //如果flag=true,就先进入A房间,再进入B房间
 8     if(flag){
 9       synchronized (A .lockA){
10         System.out.println("先进入房间A");
11           synchronized(B. lockB){
12             System.out.println("再进入房间B");
13           }
14         }
15     }else{
16        synchronized (B.lockB){
17          System.out.println("先进入房间B");
18           synchronized(A.lockA){
19             System.out.println("再进入房间B");
20           }
21         }
22      }
23    }
24   }
25 
26 }
27 
28 //建立房间A的锁
29 class A{
30   public static final A lockA=new A();
31 }
32 //建立B房间的锁
33 class B{
34   public static final B lockB=new B();
35 }
36 public class SiSuo {
37   public static void main(String[] args) {
38     Thread t1=new Thread(new Dead(true));
39     Thread t2=new Thread(new Dead(false));
40     t1.start();
41     t2.start();
42 
43   }
44 }

 

9、线程通信:

  案例一:输入一个名字,打印一个名字。

    案例中碰到的问题:

      A、数据错乱问题:第二次赋值还没完成,就输出了,导致了性别错乱。

        解决方法:  同步共享数据。

      B、数据的安全问题还没解决:

        只有2个原因:共享数据是否都同步了
               同步中的锁是同一个吗

        解决方法:  使用Resource的对象作为锁。
      C、没有交替的输出:

        原因:线程发生了阻塞,cpu资源被其他的线程抢走了

        解决方法:定义一个标记,使用等待和唤醒控制线程

      D、出现了监视器异常:

        原因:wait()和notify()如果不标明谁调用的话,就会是Object类调用的。而作为锁的对象是Resource类的对象。

        解决方法:用Resource调用wait()和notify()方法。
 

 1 public class XianCheng {
 2   public static void main(String[] args) {
 3     Resource r=new Resource();
 4 
 5     Thread tin=new Thread(new Input(r));
 6     Thread tout=new Thread(new Output(r));
 7     tin.start();
 8     tout.start();
 9   }
10 }
11 class Resource{
12   String name;
13   String sex;
14   boolean flag=false;//flag为真代表赋值完成,等待,唤醒输出;为假,代表输出完成,等待,唤醒输入;
15 
16   Resource (){}
17 }
18 class Input implements Runnable{
19   Resource r;
20 
21   Input (){}
22   Input(Resource r){
23   this.r=r;
24 }
25 
26   public void run(){
27     int x=0;
28     while(true){
29       synchronized(r){
30         if(r.flag==true){
31           try{
32             r.wait();
33           }catch(Exception e){    }
34         }
35         if(x%2==0){
36           r.name="妖姬";
37           r.sex="女";
38         }else{
39           r.name="亚索";
40           r.sex="男";
41         }
42         x++;
43         r.flag=true;
44         r.notify();
45       }
46     }
47    }
48 }
49 class Output implements Runnable{
50   Resource r;
51   Output (){}
52   Output(Resource r){
53     this.r=r;
54   }
55   public void run(){
56     while(true){
57       synchronized (r){
58         if(r.flag==false){
59           try{
60             r.wait();
61           }catch(Exception e){
62           }
63        }
64        System.out.println(r.name+"..."+r.sex);
65        r.flag=false;
66        r.notify();
67       }
68     }
69    }
70 }

 10、案例二:有一个产品,生产一个消费一个。生产四个,消费四个。

   遇到的问题:

    A、生产了多个,消费了多个

      原因:notify()会唤醒先等待的线程,不管标记此时是什么值。

      解决方法:全部唤醒后,再进行标记判断。

    B、资源浪费

      原因:唤醒了全部进程

  

 1 /* * 实现多生产和多消费
 2  * 定义产品对象 -- 生产 -- 消费
 3  * 生产者线程,控制生产
 4  * 消费者线程,控制消费
 5  */
 6 //定义产品类
 7 class Product {
 8     private String name;//品名
 9     private int count = 0 ;//计数器
10     private boolean b = false;
11     //生产方法
12     public synchronized void set(String name){
13         while(b){
14             try{this.wait();}catch(Exception e){}
15         }
16         this.name = name +".."+count++;//this.name成员变量,品名+计数器
17         System.out.println(Thread.currentThread().getName()+" 生产第.."+this.name);
18         b = true;
19         this.notifyAll();
20     }
21     //消费方法
22     public synchronized void get(){
23         while(!b){
24             try{this.wait();}catch(Exception e){}
25         }
26         System.out.println(Thread.currentThread().getName()+" 消费第......"+this.name);
27         b = false;
28         this.notifyAll();
29     }
30 }
31 //定义生产者线程
32 class Pro implements Runnable{
33     private Product p ;
34     Pro(Product p){this.p = p;}
35     public void run(){
36         while(true)
37             p.set("黄金");
38     }
39 }
40 //定义消费线程
41 class Cus implements Runnable{
42     private Product p ;
43     Cus(Product p ){this.p = p;}
44     public void run(){
45         while(true)
46             p.get();
47     }
48 }
49 public class ThreadDemo1 {
50     public static void main(String[] args) {
51         Product p = new Product();
52         Pro pro = new Pro(p);
53         Cus cus = new Cus(p);
54         Thread t0 = new Thread(pro);
55         Thread t1 = new Thread(pro);
56         Thread t2 = new Thread(pro);
57         Thread t3 = new Thread(pro);
58         
59         Thread t4 = new Thread(cus);
60         Thread t5 = new Thread(cus);
61         Thread t6 = new Thread(cus);
62         Thread t7 = new Thread(cus);
63         
64         t0.start();
65         t1.start();
66         t2.start();
67         t3.start();
68         t4.start();
69         t5.start();
70         t6.start();
71         t7.start();
72     }
73 }

 

 

 

                                          1.5后新的锁

1、java.util.concurrent.locks包中Lock接口

  替换了以前的同步机制,获得了更广泛和灵活的锁定操作

2、Lock接口中的方法:

  Lock() 获得锁

  unlock()释放锁

  synchronized(this){等同于获取锁

    }等同于释放锁

Lock接口的实现类ReentrantLock

                                            

                                          Condition接口

 

 

1、java.util.concurrent.locks包中Condition接口

 解决了同步没有后,锁也没有了,不能使用notify和wait方法的问题。

2、Condition中的方法:

  await()==wait();

  signal()==notifty();

  signalAll()==notify();

3、实现多线程通信中只唤醒一个线程的步骤

  A、导包:java.util.concurrent.locks.*;

  B、获取锁:创建Lock接口的实现类对象

   Lock lock new ReentrantLock();

  C、获取Condition对象,对线程分组管理

    lock.new condition()

  D、利用Condition对象中的方法await和signal实现等待和唤醒

 1 /*
 2  * 生产者与消费案例,改造成JDK1.5的新特性,Lock锁方式
 3  * 实现节约资源,目的唤醒对方的一个
 4  */
 5 import java.util.concurrent.locks.*;
 6 class Product {
 7     private String name;//品名
 8     private int count = 0 ;//计数器
 9     private boolean b = false;
10     
11     //获取Lock接口的实现类对象,获取锁
12     private Lock lock = new ReentrantLock();
13     private Condition pro = lock.newCondition();
14     private Condition cus = lock.newCondition();
15     
16     //生产方法
17     public  void set(String name){
18         lock.lock();
19         while(b){
20             try{pro.await();}catch(Exception e){}
21         }
22         this.name = name +".."+count++;//this.name成员变量,品名+计数器
23         System.out.println(Thread.currentThread().getName()+" 生产第.."+this.name);
24         b = true;
25         cus.signal();
26         lock.unlock();
27     }
28     //消费方法
29     public  void get(){
30         lock.lock();
31         while(!b){
32             try{cus.await();}catch(Exception e){}
33         }
34         System.out.println(Thread.currentThread().getName()+" 消费第......"+this.name);
35         b = false;
36         pro.signal();
37         lock.unlock();
38     }
39 }
40 //定义生产者线程
41 class Pro implements Runnable{
42     private Product p ;
43     Pro(Product p){this.p = p;}
44     public void run(){
45         while(true)
46             p.set("黄金");
47     }
48 }
49 //定义消费线程
50 class Cus implements Runnable{
51     private Product p ;
52     Cus(Product p ){this.p = p;}
53     public void run(){
54         while(true)
55             p.get();
56     }
57 }
58 public class ThreadLock {
59     public static void main(String[] args) {
60         Product p = new Product();
61         Pro pro = new Pro(p);
62         Cus cus = new Cus(p);
63         Thread t0 = new Thread(pro);
64         Thread t1 = new Thread(pro);
65         Thread t2 = new Thread(pro);
66         Thread t3 = new Thread(pro);
67         
68         Thread t4 = new Thread(cus);
69         Thread t5 = new Thread(cus);
70         Thread t6 = new Thread(cus);
71         Thread t7 = new Thread(cus);
72         
73         t0.start();
74         t1.start();
75         t2.start();
76         t3.start();
77         t4.start();
78         t5.start();
79         t6.start();
80         t7.start();
81     }
82 }

 

 

                                        线程的停止方法

Thread类中的stop()过时了,所以通过终止run方法来停止线程

  方法一:改变循环变量(等待中的线程停不下来)

  方法二:利用wait()方法的异常,在catch语句中改变循环变量

  Thread中中断线程的方法:void interrupt();

 

                                        线程的守护

Thread中void setDaemon(boolean on)如果传递布尔值为true,就将调用该方法的线程标记为守护线程,守卫别的线程。

 

                                          定时任务

java.util.Timer

Timer类的构造方法 Timer(boolean isDaemon)

Timer类中的方法:Schedule(执行的代码TimerTask task,开始时间,持续时间)

          执行的代码:task要实现TimerTask接口需重写run方法

 

                                Thread中的toString()方法

toString()获取线程的名字,优先级和组  

优先级 :  默认5  最低1   最高 10    

设置优先级的方法:setPriority(int newPriority)   

                                    Thread中的join方法

作用:等待该线程终止    

                                    Thread中yield方法  

线程让步

黑马程序员_多线程,布布扣,bubuko.com

黑马程序员_多线程

标签:android   style   blog   http   color   java   使用   os   

原文地址:http://www.cnblogs.com/ezreal33/p/3923162.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!