Java 多线程之间的通信

一个线程送水,一个线程出水:多个线程操作同一个资源,但操作的动作不同。两个线程操作同一资源,但操作的动作不一样。两个方法

package cn.itcast.day5.thread;

//一进一出
public class 线程通信
{
    public static void main(String[] args)
    {
        Resouce resouce = new Resouce();
        Input input = new Input(resouce);
        OutPut outPut = new OutPut(resouce);

        Thread thread1 = new Thread(input);
        Thread thread2 = new Thread(outPut);

        thread1.start();
        thread2.start();
    }
}

class Resouce
{
    public String name;
    public String sex;
}

class Input implements Runnable
{
    Resouce resouce;

    Input(Resouce resouce)
    {
        this.resouce = resouce;
    }

    @Override
    public void run()
    {
        int x = 1;
        while (true)
        {
            synchronized (Input.class)//两个线程的锁只要是一个object 在内存中的字节码
            {
                if (x == 0)
                {
                    resouce.name = "peter.peng";
                    resouce.sex = "boy";
                } else
                {
                    resouce.name = "彭运松";
                    resouce.sex = "男";
                }
                x = (x + 1) % 2;
            }
        }
    }

}

class OutPut implements Runnable
{
    Resouce resouce;

    OutPut(Resouce resouce)
    {
        this.resouce = resouce;
    }

    @Override
    public void run()
    {
        while (true)
        {
            synchronized (Input.class) //两个线程的锁只要是一个object 在内存中的字节码
            {
                System.out.println(Thread.currentThread() + "-----:" + resouce.name + ":" + resouce.sex);
            }
        }
    }
}
进水与进水的案例

 如果要达到一进一去,交替出现而不是从上一案例一样,则得用到 wait()     notify()  notityAll(),理解这几个意义

  1 package cn.itcast.day5.thread;
  2 
  3 //一进一出
  4 public class 线程通信
  5 {
  6     public static void main(String[] args)
  7     {
  8         Resouce resouce = new Resouce();
  9         Input input = new Input(resouce);
 10         OutPut outPut = new OutPut(resouce);
 11 
 12         Thread thread1 = new Thread(input);
 13         Thread thread2 = new Thread(outPut);
 14 
 15         thread1.start();
 16         thread2.start();
 17     }
 18 }
 19 
 20 class Resouce
 21 {
 22     public String name;
 23     public String sex;
 24     boolean flag=false;
 25 }
 26 
 27 class Input implements Runnable
 28 {
 29     Resouce resouce;
 30 
 31     Input(Resouce resouce)
 32     {
 33         this.resouce = resouce;
 34     }
 35 
 36     @Override
 37     public void run()
 38     {
 39         int x = 0;
 40         while (true)
 41         {
 42             synchronized (resouce)// 两个线程的锁只要是一个object 在内存中的字节码
 43             {
 44                 if(resouce.flag)
 45                     try
 46                     {
 47                         wait();
 48                         //由于第一次flag=false 所以线程1不会等待,就会执行x==0,赋一次值,赋值完后,flag=true,这时线程1
 49                         //就会等待,同是叫醒线程2.
 50                         //由于flag=true 则线程2不会等待,就会执行输出语句,输出完后,flag=false,这时线程2就会等待,同时叫醒线程1
 51                         //这时就会执行else语句给resource第二次赋值,赋完值后x=(x+1)%2,这里x=0,同时flag=true,线程1又等待。同时
 52                         //第二次叫醒线程2 .............
 53                     }
 54                     catch (Exception e)
 55                     {
 56                     }
 57                 if (x == 0)
 58                 {
 59                     resouce.name = "peter.peng";
 60                     resouce.sex = "boy";
 61                 } else
 62                 {
 63                     resouce.name = "彭运松";
 64                     resouce.sex = "男";
 65                 }
 66                 x = (x + 1) % 2;
 67                 resouce.flag = true;
 68                 resouce.notify();// 叫醒线程2
 69             }
 70         }
 71     }
 72 
 73 }
 74 
 75 class OutPut implements Runnable
 76 {
 77     Resouce resouce;
 78 
 79     OutPut(Resouce resouce)
 80     {
 81         this.resouce = resouce;
 82     }
 83 
 84     @Override
 85     public void run()
 86     {
 87         while (true)
 88         {
 89             synchronized (resouce) // 两个线程的锁只要是一个object 在内存中的字节码
 90             {
 91                 if (!resouce.flag)
 92                     try
 93                     {
 94                         resouce.wait();
 95                     }
 96                     catch (Exception e)
 97                     {
 98 
 99                     }
100                 System.out.println(resouce.name + ":" + resouce.sex);
101                 resouce.flag = false;
102                 resouce.notify();//叫醒线程1
103             }
104         }
105     }
106 }
多张程交替打印两个人名

 对等待线程的优化(上一程序) 对Resurce进行封装,并把set get 方法进行同步。

 生者消费者的例子

 1 package net.nw.entites;
 2 
 3 public class ThreadDemo_Product_Customer {
 4 
 5     public static void main(String[] args) {
 6 
 7         Resource resource = new Resource();
 8         Product product = new Product(resource);
 9         Customer customer = new Customer(resource);
10 
11         Thread t1 = new Thread(product);
12         Thread t2 = new Thread(customer);
13         Thread t3 = new Thread(product);
14         Thread t4 = new Thread(customer);
15 
16         t1.start();
17         t2.start();
18         t3.start();
19         t4.start();
20     }
21 }
22 
23 class Resource {
24     public String name;
25     public boolean flag;
26     public int count = 0;
27 
28     public synchronized void Set(String name) {
29         while (true) {
30             while(flag) {
31                 try {
32                     wait();
33                 } catch (Exception e) {
34                     e.printStackTrace();
35                 }
36             }
37             this.name = name + count++;
38             System.out.println(Thread.currentThread().getName() + "-P:"
39                     + this.name);
40             flag = true;
41             notifyAll();
42         }
43     }
44 
45     public synchronized void getOut() {
46         while (true) {
47             while (!flag) {
48                 try {
49                     wait();
50                 } catch (Exception e) {
51                     e.printStackTrace();
52                 }
53             }
54             System.out.println(Thread.currentThread().getName() + "-C:"
55                     + this.name);
56             flag = false;
57             notifyAll();
58         }
59     }
60 }
61 
62 class Product implements Runnable {
63     Resource resource;
64 
65     Product(Resource resource) {
66         this.resource = resource;
67     }
68 
69     @Override
70     public void run() {
71         resource.Set("pc");
72     }
73 }
74 
75 class Customer implements Runnable {
76     Resource resource;
77 
78     Customer(Resource resource) {
79         this.resource = resource;
80     }
81 
82     @Override
83     public void run() {
84         resource.getOut();
85     }
86 
87 }
两个以上线程的消费与生产关系

JdK1.5 新特性的多线程操作

  1 package net.nw.entites;
  2 
  3 import java.util.concurrent.locks.Condition;
  4 import java.util.concurrent.locks.Lock;
  5 import java.util.concurrent.locks.ReentrantLock;
  6 
  7 public class ThreadDemo_Product_Customer {
  8 
  9     public static void main(String[] args) {
 10 
 11         Resource resource = new Resource();
 12         Product product = new Product(resource);
 13         Customer customer = new Customer(resource);
 14 
 15         Thread t1 = new Thread(product);
 16         Thread t2 = new Thread(customer);
 17         Thread t3 = new Thread(product);
 18         Thread t4 = new Thread(customer);
 19 
 20         t1.start();
 21         t2.start();
 22         t3.start();
 23         t4.start();
 24     }
 25 }
 26 
 27 class Resource {
 28     public String name;
 29     public boolean flag;
 30     public int count = 0;
 31 
 32     final Lock lock = new ReentrantLock();
 33     final Condition notFull = lock.newCondition();
 34     final Condition notEmpty = lock.newCondition();
 35 
 36     public void Set(String name) {
 37         lock.lock();
 38         try {
 39             while (true) {
 40                 while (flag) {
 41                     try {
 42                         notFull.await();
 43                     } catch (Exception e) {
 44                         e.printStackTrace();
 45                     }
 46                 }
 47                 this.name = name + count++;
 48                 System.out.println(Thread.currentThread().getName() + "-P:"
 49                         + this.name);
 50                 flag = true;
 51                 notEmpty.signal();
 52             }
 53         } finally {
 54             lock.unlock();
 55         }
 56     }
 57 
 58     public void getOut() {
 59         lock.lock();
 60         try {
 61             while (true) {
 62                 while (!flag) {
 63                     try {
 64                         notEmpty.await();
 65                     } catch (Exception e) {
 66                         e.printStackTrace();
 67                     }
 68                 }
 69                 System.out.println(Thread.currentThread().getName() + "-C:"
 70                         + this.name);
 71                 flag = false;
 72                 notFull.signal();
 73             }
 74         } finally {
 75             lock.unlock();
 76         }
 77     }
 78 }
 79 
 80 class Product implements Runnable {
 81     Resource resource;
 82 
 83     Product(Resource resource) {
 84         this.resource = resource;
 85     }
 86 
 87     @Override
 88     public void run() {
 89         resource.Set("pc");
 90     }
 91 }
 92 
 93 class Customer implements Runnable {
 94     Resource resource;
 95 
 96     Customer(Resource resource) {
 97         this.resource = resource;
 98     }
 99 
100     @Override
101     public void run() {
102         resource.getOut();
103     }
104 
105 }
两个以上线程的生产与消费关系

说明:Lock提供更为优秀的方法来替换synchronized    lock.lock     lock.unlock(放在finally)
        await    single   singleall  分别对应  wait notify notifyAll ,但JDK1.5后提供了codition,可以为生产消费指这不同的codition,这样两个线程或是两个以上线程就可以分开出来控制
   如果是同一个codition singleAll时就会呼醒其它的线程同时也可以是同类的线程,达不到控制的效果。

线程的中断:其实只要控制住run方法的循环条件就可以了,但有一种情况下await()时就没有办法做了,因为根本就不会执行循环体的语句,这时要用到interruput,使线程势抛出一个异常InterruptedException,然后在验证循环体的条件。

  1 package net.nw.entites;
  2 
  3 import java.util.concurrent.locks.Condition;
  4 import java.util.concurrent.locks.Lock;
  5 import java.util.concurrent.locks.ReentrantLock;
  6 
  7 public class ThreadDemo_Product_Customer {
  8 
  9     public static void main(String[] args) {
 10 
 11         Resource resource = new Resource();
 12         Product product = new Product(resource);
 13         Customer customer = new Customer(resource);
 14 
 15         Thread t1 = new Thread(product);
 16         Thread t2 = new Thread(customer);
 17         Thread t3 = new Thread(product);
 18         Thread t4 = new Thread(customer);
 19         t1.start();
 20         t2.start();
 21 
 22         // t3.start();
 23         // t4.start();
 24     }
 25 }
 26 
 27 class Resource {
 28     public String name;
 29     public boolean flag;
 30     public boolean conditionFlag = true;
 31     public int count = 0;
 32 
 33     final Lock lock = new ReentrantLock();
 34     final Condition notFull = lock.newCondition();
 35     final Condition notEmpty = lock.newCondition();
 36 
 37     public void Set(String name) {
 38 
 39         lock.lock();
 40         try {
 41             while (conditionFlag) {
 42                 while (flag) {
 43                     try {
 44                         notFull.await();
 45                         Thread.currentThread().interrupt();//把当前的线程中断了。
 46                     } catch (InterruptedException e) {
 47                         conditionFlag = false;
 48                     }
 49                 }
 50                 this.name = name + count++;
 51                 System.out.println(Thread.currentThread().getName() + "-P:"
 52                         + this.name);
 53                 flag = true;
 54                 notEmpty.signal();
 55             }
 56         } finally {
 57             lock.unlock();
 58             if (Thread.interrupted()) {
 59                 System.out.println(Thread.currentThread().getName()
 60                         + ":线程中断了。。。。。。。。。。。");
 61             }
 62         }
 63     }
 64 
 65     public void getOut() {
 66 
 67         lock.lock();
 68         try {
 69             while (conditionFlag) {
 70                 while (!flag) {
 71                     try {
 72                         notEmpty.await();
 73                         Thread.currentThread().interrupt();//把当前的线程中断了。
 74                     } catch (InterruptedException e) {
 75                         conditionFlag = false;
 76                     }
 77                 }
 78                 System.out.println(Thread.currentThread().getName() + "-C:"
 79                         + this.name);
 80                 flag = false;
 81                 notFull.signal();
 82             }
 83         } finally {
 84             lock.unlock();
 85             if (Thread.interrupted()) {
 86                 System.out.println(Thread.currentThread().getName()
 87                         + ":线程中断了。。。。。。。。。。。");
 88             }
 89         }
 90     }
 91 }
 92 
 93 class Product implements Runnable {
 94     Resource resource;
 95 
 96     Product(Resource resource) {
 97         this.resource = resource;
 98     }
 99 
100     @Override
101     public void run() {
102         resource.Set("pc");
103     }
104 }
105 
106 class Customer implements Runnable {
107     Resource resource;
108 
109     Customer(Resource resource) {
110         this.resource = resource;
111     }
112 
113     @Override
114     public void run() {
115         resource.getOut();
116     }
117 
118 }
多线程安全通信的线程中断

 

线程的join   setDaemon  yield 

  1 package cn.itcast.day5.thread;
  2 
  3 class Demo1 implements Runnable
  4 {
  5     private int count = 100;
  6 
  7     @Override
  8     public void run()
  9     {
 10         while (count > 0)
 11         {
 12             System.out.println(Thread.currentThread().getName() + ":" + "------peter.peng" + count--);
 13             Thread.yield();
 14         }
 15     }
 16 }
 17 
 18 public class ThreadJionYield
 19 {
 20     public static void main(String[] args) throws InterruptedException
 21     {
 22         // SetDaemon();//设为后台线程
 23         // ThreadJoin();//join可以用来时加入线程,遇到一个线程的Join主线程冻结,其它的不变,只到Join这个线程结束,主线程再执行。
 24         // SetPriority();//设置线程的优势级
 25         Thread thread1 = new Thread(new Demo1());//yield让当前线程停止执行另一个线程。
 26         Thread thread2 = new Thread(new Demo1());
 27 
 28         thread1.start();
 29         thread2.start();
 30     }
 31 
 32     private static void SetPriority()
 33     {
 34         Thread thread1 = new Thread(new Runnable()
 35         {
 36             int count = 100;
 37 
 38             public void run()
 39             {
 40                 while (count > 0)
 41                 {
 42                     System.out.println(Thread.currentThread().toString() + "------peter.peng" + count--);
 43                 }
 44             }
 45         });
 46 
 47         Thread thread2 = new Thread(new Runnable()
 48         {
 49             int count = 100;
 50 
 51             public void run()
 52             {
 53                 while (count > 0)
 54                 {
 55                     System.out.println(Thread.currentThread().toString() + "------peter.peng" + count--);
 56                 }
 57             }
 58         });
 59 
 60         thread1.start();
 61         thread1.setPriority(Thread.MAX_PRIORITY);// 设线程的优化级
 62         thread2.start();
 63 
 64         System.out.println(Thread.currentThread().toString());
 65     }
 66 
 67     private static void ThreadJoin() throws InterruptedException
 68     {
 69         Thread thread1 = new Thread(new Runnable()
 70         {
 71             int count = 100;
 72 
 73             public void run()
 74             {
 75                 while (count > 0)
 76                 {
 77                     System.out.println(Thread.currentThread() + "------peter.peng" + count--);
 78                 }
 79             }
 80         });
 81 
 82         Thread thread2 = new Thread(new Runnable()
 83         {
 84             int count = 100;
 85 
 86             public void run()
 87             {
 88                 while (count > 0)
 89                 {
 90                     System.out.println(Thread.currentThread() + "------peter.peng" + count--);
 91                 }
 92             }
 93         });
 94 
 95         thread1.start();
 96         // thread1.join();//说明thread1要主线程的执行权,这个时候主线程就会冻结了,只到它不要了才会给主线程,如果把它放在后面来执行
 97         thread2.start();
 98         thread1.join();// 这时thread1 与thread2交才替出现,只到结束才执行主线程的方法。
 99 
100         System.out.println(Thread.currentThread() + ":main");
101     }
102 
103     private static void SetDaemon()
104     {
105         Thread thread1 = new Thread(new Runnable()
106         {
107             int count = 0;
108 
109             public void run()
110             {
111                 while (true)
112                 {
113                     System.out.println("------peter.peng" + count++);
114                 }
115             }
116         });
117 
118         Thread thread2 = new Thread(new Runnable()
119         {
120             int count = 0;
121 
122             public void run()
123             {
124                 while (true)
125                 {
126                     System.out.println("------peter.peng" + count++);
127                 }
128             }
129         });
130         thread1.setDaemon(true);// 设为后台线程
131         thread2.setDaemon(true);// 设为后台线程
132         thread1.start();
133         thread2.start();
134         System.out.println("over");
135     }
136 }
线程的Join,setDaemon yield

 

 

posted on 2013-05-15 20:11  peter.peng  阅读(242)  评论(0)    收藏  举报