黑马Java学习笔记之-----多线程

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

线程:

  线程是一个程序内部的顺序控制流(执行路径)。

线程和进程的区别:

  (1):每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。

  (2):线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。

  (3):多进程:在操作系统中能同时运行多个任务(程序)。

  (4):多线程:在同一应用程序中有多个顺序流同时执行。

 

  • Java的线程是通过java.lang.Thread类来实现的。
  • VM启动时会有一个由主方法(main方法)所定义的线程。
  • 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。run()方法结束,线程就结束了。
  • 通过调用Thread类的start()方法来启动一个线程。

 

创建线程的第一种方式:继承Thread类。
步骤:
1 ,定义类继承Thread
2,复写Thread类中的run方法
目的:将自定义代码存储在run方法中,让线程运行。
3,调用线程的start方法,该方法两个作用:启动线程,调用run方法

发现每一次结果都不同。

因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)

cpu在做着快速的切换,以达到看上去是同时运行的效果。

我们可以形象的把多线程的运行行为看作在互相抢夺cpu的执行权。

这就是多线程的一个特性,随机性。谁抢到,谁执行,至于执行多长,cpu说了算。

创建线程的第二种方式:实现Runable接口。

步骤:

1,定义类实现Runnable接口

2,覆盖Runnable接口中的run方法。

将线程要运行的代码存放在该run方法中。

3,通过Thread类建立线程对象。

4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。

为什么要将Runnable接口的子类对象传递给Thread的构造函数。

因为,自定义的run方法所属的对象是Runnable接口的子类对象。

所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。

5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

 

实现Runnable接口相对于继承Thread类来说,有如下优势:

1. 适合多个相同程序代码的线程去处理同一资源的情况。

2. 可以避免由于Java的单继承特性带来的局限。

3. 增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。

建议使用Runnable接口实现多线程)。

 

线程状态的转换:

 

 

线程的同步:

多线程运行出现安全问题的原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。

解决办法:同步代码块。

synchronized(对象)

{

需要被同步的代码

}

对象如同锁,持有锁的线程可以在同步中执行。

没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

同步的前提:

1. 必须要有两个或者两个以上的线程。

2. 必须是多个线程使用同一个锁。

同步函数的锁是this(当前对象)

静态同步函数的锁是Class对象(该方法所在类的字节码文件对象)。类名。class

 

 1 public class SyncTest implements Runnable{
 2 
 3     Timer timer = new Timer();
 4     public static void main(String[] args) {
 5         SyncTest stest = new SyncTest();
 6         Thread t1 = new Thread(stest,"t1");
 7         Thread t2 = new Thread(stest,"t2");
 8         t1.start();
 9         t2.start();
10 
11     }
12     
13     public void run(){
14         timer.add(Thread.currentThread().getName());
15     }
16 
17 }
18 
19 class Timer{
20     private static  int num = 0;
21     
22     public synchronized void add(String name){  //不加synchronized会出现安全问题
23         num++;
24         try{
25             Thread.sleep(1);
26         }catch(InterruptedException e){
27             
28         }
29         System.out.println(name+":你是第"+num+"个使用Timer的线程");
30     }
31 }

 

 

死锁:

  是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。

一个死锁程序:

 1 public class TestDeadLock implements Runnable {
 2     public int flag = 1;
 3     static Object o1 = new Object(), o2 = new Object();
 4     public void run() {
 5 System.out.println("flag=" + flag);
 6         if(flag == 1) {
 7             synchronized(o1) {
 8                 try {
 9                     Thread.sleep(500);
10                 } catch (Exception e) {
11                     e.printStackTrace();
12                 }
13                 synchronized(o2) {
14                     System.out.println("1");    
15                 }
16             }
17         }
18         if(flag == 0) {
19             synchronized(o2) {
20                 try {
21                     Thread.sleep(500);
22                 } catch (Exception e) {
23                     e.printStackTrace();
24                 }
25                 synchronized(o1) {
26                     System.out.println("0");
27                 }
28             }
29         }
30     }    
31     
32     public static void main(String[] args) {
33         TestDeadLock td1 = new TestDeadLock();
34         TestDeadLock td2 = new TestDeadLock();
35         td1.flag = 1;
36         td2.flag = 0;
37         Thread t1 = new Thread(td1);
38         Thread t2 = new Thread(td2);
39         t1.start();
40         t2.start();
41         
42     }
43 }

 

 生产者消费者问题:

 

  1 //java多线程模拟生产者消费者问题
  2 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品
  3 //Storage仓库
  4 
  5 public class ProducerConsumer {
  6 
  7     public static void main(String[] args) {
  8         Storage s = new Storage();
  9         Producer p = new Producer(s);
 10         Consumer c = new Consumer(s);
 11         Thread tp = new Thread(p);
 12         Thread tc = new Thread(c);
 13         tp.start();
 14         tc.start();
 15 
 16     }
 17 }
 18 
 19 class Consumer implements Runnable {//消费者    
 20     Storage s = null;
 21     public Consumer(Storage s){
 22         this.s = s;
 23     }
 24     public void run() {
 25         for(int i=0; i<20; i++){
 26             Product p = s.pop();//取出产品
 27             try {
 28                 Thread.sleep((int)(Math.random()*1500));
 29             } catch (InterruptedException e) {
 30                 e.printStackTrace();
 31             }
 32         }
 33         
 34     }
 35 
 36 }
 37 
 38 class Producer implements Runnable {//生产者
 39     Storage s = null;
 40     
 41     public Producer(Storage s){
 42         this.s = s;
 43     }
 44 
 45     public void run() {
 46         for(int i=0; i<20; i++){
 47             Product p = new Product(i);
 48             s.push(p);    //放入产品
 49 //            System.out.println("生产者放入:" + p);
 50             try {
 51                 Thread.sleep((int)(Math.random()*1500));
 52             } catch (InterruptedException e) {
 53                 e.printStackTrace();
 54             }
 55         }
 56 
 57     }
 58 }
 59 
 60 class Product {
 61     int id;
 62     
 63     public Product(int id){
 64         this.id = id;
 65     }
 66     
 67     public String toString(){//重写toString方法
 68         return "产品:"+this.id;
 69     }
 70 }
 71 
 72 
 73 class Storage {
 74     int index = 0;
 75     Product[] products = new Product[5];
 76     
 77     public synchronized void push(Product p){//放入
 78         while(index==this.products.length){
 79             try {
 80                 this.wait();
 81             } catch (InterruptedException e) {
 82                 e.printStackTrace();
 83             }
 84         }
 85         this.products[index] = p;
 86         System.out.println("生产者放入"+index+"位置:" + p);
 87         index++;
 88         this.notifyAll();
 89     }
 90     
 91     public synchronized Product pop(){//取出
 92         while(this.index==0){
 93             try {
 94                 this.wait();
 95             } catch (InterruptedException e) {
 96                 e.printStackTrace();
 97             }
 98         }
 99         index--;
100         this.notifyAll();
101         System.out.println("消费者从"+ index+ "位置取出:" + this.products[index]);
102         return this.products[index];
103     }
104 }

 

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

 

 

posted @ 2013-04-29 02:07  Mercy_K  阅读(303)  评论(0编辑  收藏  举报