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

黑马程序员---java基础-Java 多线程

时间:2015-04-25 10:37:17      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

 

进程指的是一个正在执行中的程序,而线程则是进程中一个负责程序执行的控制单元。一个进程中可以有多个执行路径,这就是多线程。开启多个线程可以运行多部分代码,这样就能运行多个功能

一、多线程的创建

java中,创建多线程主要有以下两个方式:

1、继承Thread类:

 1 public class test {
 2 
 3   public static void main(String[] args) {
 4 
 5       //创建对象
 6 
 7       ProducerProject p1=new ProducerProject();
 8 
 9       p1.setName("生产者1");
10 
11       ProducerProject p2=new ProducerProject();
12 
13       p2.setName("生产者2");
14 
15       //开始执行线程
16 
17       p1.start();
18 
19       p2.start();
20 
21   }
22 
23 }
24 
25 //继承Thread类
26 
27 class ProducerProject extends Thread{
28 
29   //覆盖Thread类中 的run()方法
30 
31   public void run(){
32 
33       for(int i=0;i<5;i++){
34 
35           System.out.println(Thread.currentThread().getName()+"..生产商品"+i);
36 
37       }
38 
39   }
40 
41 }

 

2、实现Runnable接口

 1 public class test2{
 2     public static void main(String[] args){
 3         //创建ProducerProject2对象
 4         ProducerProject2 p=new ProducerProject2();
 5         //将p作为参数构造Thread对象,创建线程
 6         Thread t1=new Thread(p);
 7         Thread t2=new Thread(p);
 8 
 9         t1.setName("生产者1");
10         t2.setName("生产者1");
11         //启动线程
12         t1.start();
13         t2.start();
14     }
15 }
16 
17 //实现Runnable接口
18 class ProducerProject2 implements Runnable{
19     //实现run()方法
20     public void run() {
21         for(int i=0;i<5;i++){
22             System.out.println(Thread.currentThread().getName()+"..生产商品"+i);
23         }
24     }
25 }

 

实现Runnable接口避免了单继承的局限性,并且可以实现资源的共享,适合多个相同的程序代码的线程去处理同一资源,所以一般建议使用第二种线程创建方式。我们可以用静态方法currentThread()来获取当前线程对象,getName()setName()可以用来获取和设置线程名称。

二、synchronized 锁和waitnotifynotifyAll 应用

 1 /*
 2  * 线程间通信
 3  * 其实是多个线程在操作同一个资源
 4  * 但是操作的动作不同
 5  * 
 6  * 等待 唤醒机制 
 7  * 
 8  * wait()
 9  * nitify()
10  * notifyAll() 
11  * 都使用在同步中。
12  * 因为要对持有监视器(锁)的线程操作
13  * 所以要使用在同步中,只有同步才具有锁
14  * 为什么这些操作要定义在Object类中
15  * 因为这些方法在操作同步线程中,都必须
16  * 标示他们所操作线程中的锁
17  * 只有同一个锁上的被等待线程,
18  * 可以被同一个锁上的notify 唤醒
19  * 不可以对不同锁上的线程进行唤醒
20  * 
21  * 也就是说,等待唤醒的线程必须是同一个锁上
22  * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在
23  * Object类
24  * 
25  * */
26 class Res{
27     String name;
28     String sex;
29     boolean rw=false;
30 }
31 class Input implements Runnable{
32     Res res;
33     public Input(Res res) {
34         this.res=res;
35     }
36     public void run() {
37         boolean flag=true;
38         while (true) {
39             synchronized (res) {
40                 if(res.rw)
41                     try {
42                         res.wait();
43                     } catch (InterruptedException e) {
44                         e.printStackTrace();
45                     }
46                 if (flag) {
47                     res.name="mike";
48                     res.sex="man";
49                 }else {
50                     res.name="丽丽";
51                     res.sex="女";
52                 }
53                 flag=flag==true?false:true;
54                 res.rw=true;
55                 res.notify();
56             }
57         }
58     }
59 }
60 class Output implements Runnable{
61     Res res;
62     public Output(Res res) {
63         this.res=res;
64     }
65     public void run() {
66         while (true) {
67             synchronized (res) {
68                 if(!res.rw)
69                     try {
70                         res.wait();
71                     } catch (InterruptedException e) {
72                         e.printStackTrace();
73                     }
74                 System.out.println(res.name+"-"+res.sex);
75                 res.rw=false;
76                 res.notify();
77             }
78         }
79     }
80 }
81 public class InputOutputDemo {
82     public static void main(String[] args) {
83         Res res=new Res();
84         Input input=new  Input(res);
85         Output output=new Output(res);
86         Thread threadIn=new Thread(input);
87         Thread threadOut=new Thread(output);
88         threadIn.start();
89         threadOut.start();
90     }
91 
92 }

-----------可以对代码进行优化,得到以下代码

 1 /*
 2  * 线程间通信
 3  * 其实是多个线程在操作同一个资源
 4  * 但是操作的动作不同
 5  * 
 6  * 等待 唤醒机制 
 7  * 
 8  * wait()
 9  * nitify()
10  * notifyAll() 
11  * 都使用在同步中。
12  * 因为要对持有监视器(锁)的线程操作
13  * 所以要使用在同步中,只有同步才具有锁
14  * 为什么这些操作要定义在Object类中
15  * 因为这些方法在操作同步线程中,都必须
16  * 标示他们所操作线程中的锁
17  * 只有同一个锁上的被等待线程,
18  * 可以被同一个锁上的notify 唤醒
19  * 不可以对不同锁上的线程进行唤醒
20  * 
21  * 也就是说,等待唤醒的线程必须是同一个锁上
22  * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在
23  * Object类中
24  * 
25  * ------------------------------代码优化-----------------------------------
26  * */
27 class Res2{
28     private String name;
29     private String sex;
30     private boolean rw=false;
31     public synchronized void setNameSex(String name,String sex) {
32         if (rw) {
33             try {
34                 this.wait();
35             } catch (InterruptedException e) {
36                 e.printStackTrace();
37             }
38         }
39         this.name = name;
40         this.sex = sex;
41         rw=true;
42         this.notify();
43     }
44     public synchronized void getSexName() {
45         if (!rw) {
46             try {
47                 this.wait();
48             } catch (InterruptedException e) {
49                 e.printStackTrace();
50             }
51         }
52         System.out.println(name+"---"+sex);
53         rw=false;
54         this.notify();
55     }
56 }
57 class Input2 implements Runnable{
58     Res2 res;
59     public Input2(Res2 res) {
60         this.res=res;
61     }
62     public void run() {
63         boolean flag=true;
64         while (true) {
65             
66                 if (flag) {
67                     res.setNameSex("mike","man");
68                 }else {
69                     res.setNameSex("丽丽","女");
70                 }
71                 flag=flag==true?false:true;
72             }
73         }
74 }
75 class Output2 implements Runnable{
76     Res2 res;
77     public Output2(Res2 res) {
78         this.res=res;
79     }
80     public void run() {
81         while (true) {
82                 res.getSexName();
83             }
84         }
85 }
86 public class InputOutputDemo2 {
87     public static void main(String[] args) {
88         Res2 res=new Res2();
89 //        Input2 input=new  Input2(res);
90 //        Output2 output=new Output2(res);
91 //        Thread threadIn=new Thread(input);
92 //        Thread threadOut=new Thread(output);
93 //        threadIn.start();
94 //        threadOut.start();
95         new Thread(new  Input2(res)).start();
96         new Thread(new Output2(res)).start();
97         
98     }
99 }

 

三、用Lock 代替synchronized 实现线程同步

  1 import java.util.concurrent.locks.Condition;
  2 import java.util.concurrent.locks.Lock;
  3 import java.util.concurrent.locks.ReentrantLock;
  4 
  5 /*对于多个生产者和消费者
  6  * 为什么要定义while 判断标记
  7  * 原因:为了让被唤醒的线程再一次判断标记
  8  * 
  9  * 为什么定义notifyAll()
 10  * 因为需要唤醒对方线程
 11  * 因为只用notify ,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待
 12  * 
 13  * 
 14  * jdk 1.5 中国提供了多线程升级解决方案
 15  * 将同步 的synchronized替换成Lock操作
 16  * 将 Object 中的 wait  notify   notifyAll 替换了Condition  对象
 17  * 该对象可以Lock锁进行获取
 18  * 在该例子中,实现了本方只唤醒对方线程操作
 19  * */
 20 public class ProduceConsumeLockDemo {
 21 
 22     public static void main(String[] args) {
 23         Resource2 resource=new Resource2();
 24         Produce2 produce=new Produce2(resource);
 25         Consume2 consume=new Consume2(resource);
 26         
 27         Thread threadPro1=new Thread(produce);
 28         Thread threadPro2=new Thread(produce);
 29         Thread threadConsume2e1=new Thread(consume);
 30         Thread threadConsume2e2=new Thread(consume);
 31         threadPro1.start();
 32         threadPro2.start();
 33         threadConsume2e1.start();
 34         threadConsume2e2.start();
 35     }
 36 
 37 }
 38 class Produce2 implements Runnable{
 39     private Resource2 resource;
 40     public Produce2(Resource2 resource) {
 41         this.resource=resource;
 42     }
 43     public  void run() {
 44         while (true) {
 45             try {
 46                 resource.set("+商品+");
 47             } catch (InterruptedException e) {
 48                 e.printStackTrace();
 49             }
 50         }
 51     }
 52 }
 53 class Consume2 implements Runnable{
 54     private Resource2 resource;
 55     public Consume2(Resource2 resource) {
 56         this.resource=resource;
 57     }
 58     public  void run() {
 59         while (true) {
 60             try {
 61                 resource.out();
 62             } catch (InterruptedException e) {
 63                 e.printStackTrace();
 64             }
 65         }
 66     }
 67     
 68 }
 69 class Resource2{
 70     private String name;
 71     private int count =1;
 72     private boolean flag=false;
 73     //---------------------------------------------------------
 74     private Lock lock =new ReentrantLock();
 75     private Condition con_Produce=lock.newCondition();
 76     private Condition con_Consume=lock.newCondition();
 77     //---------------------------------------------------------
 78     public  void set (String name)throws InterruptedException {
 79         lock.lock();//----------------------- 
 80             try {
 81                 while(flag){ 
 82 //                    con.await();
 83                     con_Produce.await();
 84                 }
 85                 this.name=name+"--"+count++;
 86                 System.out.println(Thread.currentThread().getName()+"--生产者--"+this.name);
 87                 flag=true;
 88 //                con.signal();
 89 //                con.signalAll();//还是唤醒了所有线程
 90                 con_Consume.signal();
 91             }finally{
 92                 lock.unlock();//--------------
 93                 //释放锁的动作一定要执行
 94             }
 95     }
 96     public  void out() throws InterruptedException{
 97         lock.lock();//进来,先拿到锁
 98         try {
 99             while(!flag){
100                 con_Consume.await();
101             }
102             System.out.println(Thread.currentThread().getName()+"----消费者-----"
103 + this.name);
104             flag=false;
105 //con.signal();
106             con_Produce.signal();
107         }finally{
108             lock.unlock();
109         }
110         
111     }
112 }

四、Threadstop()方法和interrup()方法

 1 /*
 2  * stop 方法以及过时
 3  * 如何停止线程
 4  * 只有一种方法 run 方法 运行结束
 5  * 
 6  * 开启多线程运行,运行代码通常是循环结构
 7  * 只要控制住循环,就可以让run方法结束,也就是线程结束
 8  * 
 9  * 特殊情况
10  * 当线程处于冻结状态,就不会读到标记
11  * 那么线程就不会结束
12  * 
13  * interrupt 强制将冻结状态的线程 运行起来  
14  * 当没有指定的方式让冻结的线程回复都爱运行状态时
15  * 
16  * 这时需要对冻结状态进行清除
17  * 强制让线程恢复到运行状态中来,就可以操作标记你,让线程结束
18  * Thread类 interrupt 提供了该功能
19  * 
20  * 守护线程 或者 用户线程
21  * 
22  * 标记为后台线程  :
23  * 处理结束和普通线程有区别外,其他都一样
24  * 当所有前台线程都结束后,后台线程自动结束(有依赖的意思)
25  * 主线程是前台线程。
26  * 当正在运行的线程都是守护线程是。jvm自动停止
27  * */
28 public class StopThreadDemo {
29     public static void main(String[] args) {
30         StopThread st=new StopThread();
31         Thread t1=new Thread(st);
32         Thread t2=new Thread(st);
33         t1.setDaemon(true);
34         t2.setDaemon(true);
35         t1.start();
36         t2.start();
37         
38         int num=0;
39         while (true) {
40             if (num++==60) {
41 //                st.changFlag();
42 //                t1.interrupt();
43 //                t2.interrupt();
44                 break;
45             }
46             System.out.println(Thread.currentThread().getName()+"main -"+num);
47         }
48         System.out.println("over");
49     }
50 }
51 class StopThread implements Runnable{
52     private boolean flag=true;
53     public synchronized void run() {
54         while(flag){
55             try {
56                 wait();
57             } catch (InterruptedException e) {
58 //                e.printStackTrace();
59                 System.out.println(Thread.currentThread().getName()+"----InterruptedException");
60                 flag=false;
61             }
62             System.out.println(Thread.currentThread().getName()+"----run");
63         }
64     }
65     public void changFlag(){
66         flag=false;
67     }
68 }

 

五、Threadjoin()方法

 1 /*
 2  * 当 A线程执行到了 B线程的Join方法时
 3  * A线程就会等待B线程终止,A才会 执行
 4  * join可以用来临时加入线程执行
 5  * 
 6  * Thread[Thread-0,5,main]--- run29
 7 Thread[Thread-1,5,main]--- run32
 8 Thread[Thread-0,5,main]--- run30
 9 Thread【线程名,优先级,线程组】 一般谁开启了线程,线程属于哪个组
10 优先级 代表 使用cpu 的使用频率
11 默认优先级是  5
12 优先级 分 1 ----10 级
13 static int MAX_PRIORITY     10
14           线程可以具有的最高优先级。 
15 static int MIN_PRIORITY     1
16           线程可以具有的最低优先级。 
17 static int NORM_PRIORITY    5
18           分配给线程的默认优先级。 
19 
20  * */
21 public class ClassJoinDemo  {
22     public static void main(String[] args) throws Exception {
23         JoinDmeo joinDmeo=new JoinDmeo();
24         Thread thread1=new Thread(joinDmeo);
25         Thread thread2=new Thread(joinDmeo);
26         
27         thread1.start();
28 //        thread1.setPriority(Thread.MAX_PRIORITY);
29         
30 //        thread1.join();
31         /*thread1.join();
32          * thread1 请求执行权
33          * 主线程处于冻结状态
34          * thread1 结束后 主线程才恢复到运行状态
35          * 等待这个线程 终止
36          * 当进行多线程运行时,
37          * 临时加入一个线程,让这个线程运算完,
38          * */
39         thread2.start();
40 //        thread1.join();
41         for (int i = 0; i < 80; i++) {
42             System.out.println("mian "+i);
43         }
44         System.out.println("mina over");
45     }
46 
47 }
48 class JoinDmeo implements Runnable{
49     public void run() {
50         for (int i = 0; i < 70; i++) {
51             System.out.println(Thread.currentThread().toString()+"--- run"+i);
52             Thread.yield();//  释放执行权
53         }
54     }
55     
56 }

 

 

黑马程序员---java基础-Java 多线程

标签:

原文地址:http://www.cnblogs.com/ZkSnug/p/4455463.html

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