线程之间的通信

原文:http://edisonxu.org/2017/03/02/java-thread-communication.html

题目: 编写两个线程,一个线程打印1~25,另一个线程打印字母A~Z,打印顺序为12A34B56C……5152Z,要求使用线程间的通信。

通用代码 

package ThreadLearnCommunicate;

import java.util.concurrent.ExecutorService;  

import java.util.concurrent.Executors;  

  

/**

* Created by Edison Xu on 2017/3/2.

*/  

public enum Helper {  

  

    instance;  

  

    private static final ExecutorService tPool =  Executors.newFixedThreadPool(2);  

  

    public static String[] buildNoArr(int max) {  

        String[] noArr = new String[max];  

        for(int i=0;i<max;i++){  

            noArr[i] = Integer.toString(i+1);  

        }  

        return noArr;  

    }  

  

    public static String[] buildCharArr(int max) {  

        String[] charArr = new String[max];  

        int tmp = 65;  

        for(int i=0;i<max;i++){  

            charArr[i] =  String.valueOf((char)(tmp+i));  

        }  

        return charArr;  

    }  

  

    public static void print(String... input){  

        if(input==null)  

            return;  

        for(String each:input){  

            System.out.print(each);  

        }  

    }  

  

    public void run(Runnable r){  

        tPool.submit(r);  

    }  

  

    public void shutdown(){  

        tPool.shutdown();  

    }  

  

}

 

 

1.synchronized + notify + wait +flag(控制变量)

 

package ThreadLearnCommunicate;

public class MethordOne {

    private ThreadToGo go = new ThreadToGo();

    public Runnable Threadone(){

         final String[] inputArr=  Helper.buildCharArr(26);

         return new Runnable() {

             public void run() {

                 for(int i  =0;i<inputArr.length;i++){

             

                     synchronized (go) {

                          while(go.value==1){

                              try {

                                  go.wait();

                              } catch  (InterruptedException e) {

                                  // TODO  Auto-generated catch block

                                  //e.printStackTrace();

                              }

                          }

                          Helper.print(inputArr[i]);

                          go.value=1;

                          go.notify();

                     }

                 }

             }

         };

         

    }

    public Runnable Threadtwo(){

         final String[] inputArr=  Helper.buildNoArr(52);

         return new Runnable() {

             public void run() {

                 for(int i  =0;i<inputArr.length;i+=2){

             

                     synchronized (go) {

                          while(go.value==2){

                              try {

                                  go.wait();

                              } catch  (InterruptedException e) {

                                  // TODO  Auto-generated catch block

                                  //e.printStackTrace();

                              }

                          }

                          Helper.print(inputArr[i],inputArr[i+1]);

                          go.value=2;

                          go.notify();

                     }

                 }

             }

         };

         

    }

    public static void main(String[] args) {

         MethordOne m =new MethordOne();

         Helper.instance.run(m.Threadone());

         Helper.instance.run(m.Threadtwo());

         Helper.instance.shutdown();

    }

    class ThreadToGo{

         int value =1;

    }

}

 

2.使用lock和condition+flag

 

package ThreadLearnCommunicate;

 

 

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

 

import ThreadLearnCommunicate.MethordOne.ThreadToGo;

 

 

public class MethordTwo {

    private Lock lock =new ReentrantLock(true);

    private Condition condition = lock.newCondition();

    private ThreadToGo go = new ThreadToGo();

    public Runnable Threadone(){

        final String[] inputArr= Helper.buildCharArr(26);

        return new Runnable() {

            public void run() {

                for(int i =0;i<inputArr.length;i++){

                    lock.lock();

                            try {

                                while(go.value==1)

                                    condition.await();

                                Helper.print(inputArr[i]);

                                go.value=1;

                                condition.signal();

                            } catch (InterruptedException e) {

                                // TODO Auto-generated catch block

                                //e.printStackTrace();

                            }finally {

                                lock.unlock();

                            }

                        

                        

                    }

            }

        };}

    public Runnable Threadtwo(){

        final String[] inputArr= Helper.buildNoArr(52);

        return new Runnable() {

            public void run() {

                for(int i =0;i<inputArr.length;i+=2){

                    lock.lock();

                        

                            try {

                                while(go.value==2)

                                    condition.await();

                                Helper.print(inputArr[i],inputArr[i+1]);

                                go.value=2;

                                condition.signal();

                            } catch (InterruptedException e) {

                                // TODO Auto-generated catch block

                                //e.printStackTrace();

                            }finally {

                                lock.unlock();

                            }

                        }

                        

                    }

            

        };}

    public static void main(String[] args) {

        MethordTwo m =new MethordTwo();

        Helper.instance.run(m.Threadone());

        Helper.instance.run(m.Threadtwo());

        Helper.instance.shutdown();

    }

    class ThreadToGo{

        int value =1;

    }

}

 

 

3.使用 volatile关键字 volatile修饰的变量值直接存在main memory里面,子线程对该变量的读写直接写入main memory,而不是像其它变量一样在local thread里面产生一份copy。volatile能保证所修饰的变量对于多个线程可见性,即只要被修改,其它线程读到的一定是最新的值。

package ThreadLearnCommunicate;

 

 

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

 

import ThreadLearnCommunicate.MethordOne.ThreadToGo;

 

 

public class MethordThree {

    private volatile  ThreadToGo go = new ThreadToGo();

 

 

    public Runnable Threadone() {

        final String[] inputArr = Helper.buildCharArr(26);

        return new Runnable() {

            

            public void run() {

                for (int i = 0; i < inputArr.length; i++) {

                    while(go.value==1){}

                        Helper.print(inputArr[i]);

                    go.value = 1;

                }

            }

        };

    }

 

 

    public Runnable Threadtwo() {

        final String[] inputArr = Helper.buildNoArr(52);

        return new Runnable() {

            private String[] arr = inputArr;

            public void run() {

                

                for (int i = 0; i < arr.length; i += 2) {

                    while(go.value==2){}

                            Helper.print(inputArr[i],inputArr[i+1]);

                        go.value = 2;

                }

            }

        };

    }

 

 

    public static void main(String[] args) {

        MethordThree m = new MethordThree();

        Helper.instance.run(m.Threadone());

        Helper.instance.run(m.Threadtwo());

        Helper.instance.shutdown();

    }

 

 

    class ThreadToGo {

        int value = 1;

    }

}

 

 

4.通过AtomicInteger类实现(AtomicInteger是一个线程安全的类

package ThreadLearnCommunicate;

 

 

import java.util.concurrent.atomic.AtomicInteger;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

 

import ThreadLearnCommunicate.MethordOne.ThreadToGo;

 

 

public class MethordFour {

    private AtomicInteger go =new AtomicInteger(1);

 

 

    public Runnable Threadone() {

        final String[] inputArr = Helper.buildCharArr(26);

        return new Runnable() {

            public void run() {

                for (int i = 0; i < inputArr.length; i++) {

                    while(go.get()==1){}

                    Helper.print(inputArr[i]);

                    go.set(1);

                    

                }

            }

        };

    }

 

 

    public Runnable Threadtwo() {

        final String[] inputArr = Helper.buildNoArr(52);

        return new Runnable() {

            public void run() {

                for (int i = 0; i < inputArr.length; i += 2) {

                    while (go.get()==2) {}

                        Helper.print(inputArr[i],inputArr[i+1]);

                        go.set(2);

                }

            }

        };

    }

 

 

    public static void main(String[] args) {

        MethordFour m = new MethordFour();

        Helper.instance.run(m.Threadone());

        Helper.instance.run(m.Threadtwo());

        Helper.instance.shutdown();

    }

 

 

}

 

 

5.利用CyclicBarrierAPI实现 CyclicBarrier可以实现让一组线程在全部到达Barrier时(执行await()),再一起同时执行,并且所有线程释放后,还能复用它,即为Cyclic。

package ThreadLearnCommunicate;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import java.util.concurrent.BrokenBarrierException;

import java.util.concurrent.CyclicBarrier;

public class MethordFive {

    private final CyclicBarrier barrier;

    private final List<String> list;

    public MethordFive(){

         list = Collections.synchronizedList(new  ArrayList<String>());

         barrier = new CyclicBarrier(2,  newBarrierAction());

         // TODO Auto-generated constructor stub

    }

    public Runnable Threadone() {

         final String[] inputArr =  Helper.buildCharArr(26);

         return new Runnable() {

             public void run() {

                 for (int i = 0; i <  inputArr.length; i++) {

                     list.add(inputArr[i]);

                     try {

                          barrier.await();

                     } catch (InterruptedException  | BrokenBarrierException e) {

                          // TODO Auto-generated  catch block

                          e.printStackTrace();

                     }

                 }

             }

         };

    }

    public Runnable Threadtwo() {

         final String[] inputArr =  Helper.buildNoArr(52);

         return new Runnable() {

             public void run() {

                 for (int i = 0; i <  inputArr.length; i += 2) {

                     list.add(inputArr[i]);

                     list.add(inputArr[i+1]);

                     try {

                          barrier.await();

                     } catch (InterruptedException  | BrokenBarrierException e) {

                          // TODO Auto-generated  catch block

                          e.printStackTrace();

                     }

                     }

                 }

         };

    }

    private Runnable newBarrierAction(){

         return new Runnable() {

             public void run() {

                 Collections.sort(list);

                 list.forEach(c->System.out.print(c));

                 list.clear();

             }

         };

    }

    public static void main(String[] args) {

         MethordOne m = new MethordOne();

         Helper.instance.run(m.Threadone());

         Helper.instance.run(m.Threadtwo());

         Helper.instance.shutdown();

    }

}

6.利用BlockingQueue

package ThreadLearnCommunicate;

import java.util.concurrent.LinkedBlockingQueue;

import java.util.concurrent.atomic.AtomicInteger;

public  class MethodSix{

    private   LinkedBlockingQueue<String>  blockingQueue = new LinkedBlockingQueue<>();

    public Runnable Threadone() {

         final String[] inputArr =  Helper.buildCharArr(26);

         return new Runnable() {

             public void run() {

                 

                 for (int i = 0; i <  inputArr.length; i++) {

                     blockingQueue.offer("twoGo");

                     while(!"oneGo".equals(blockingQueue.peek())){}

                     Helper.print(inputArr[i]);

                     blockingQueue.poll();

                     

                 }

             }

         };

    }

    public Runnable Threadtwo() {

         final String[] inputArr =  Helper.buildNoArr(52);

         return new Runnable() {

             public void run() {

                 

                 for (int i = 0; i <  inputArr.length; i++) {

                     while(!"twoGo".equals(blockingQueue.peek())){}

                     blockingQueue.poll();

                     Helper.print(inputArr[i],inputArr[i+1]);

                     blockingQueue.offer("oneGo");

                     

                 }

             }

         };

    }

    public static void main(String[] args) {

         MethodSix m = new MethodSix();

         Helper.instance.run(m.Threadone());

         Helper.instance.run(m.Threadtwo());

         Helper.instance.shutdown();

    }

}

第二种实现,通过定义两个阻塞队列

package ThreadLearnCommunicate;

import java.util.concurrent.LinkedBlockingQueue;

import java.util.concurrent.atomic.AtomicInteger;

public  class MethodSix{

    private final LinkedBlockingQueue<String>  queue1 = new LinkedBlockingQueue<>();

    private final LinkedBlockingQueue<String>  queue2 = new LinkedBlockingQueue<>();

    public Runnable newThreadThree() {

        final String[] inputArr =  Helper.buildNoArr(52);

        return new Runnable() {

            private String[] arr = inputArr;

            public void run() {

                for (int i = 0; i < arr.length;  i=i+2) {

                    Helper.print(arr[i], arr[i +  1]);

                    try {

                        queue2.put("TwoToGo");

                        queue1.take();

                    } catch (InterruptedException e)  {

                        e.printStackTrace();

                    }

                }

            }

        };

    }

    public Runnable newThreadFour() {

        final String[] inputArr =  Helper.buildCharArr(26);

        return new Runnable() {

            private String[] arr = inputArr;

            public void run() {

                for (int i = 0; i < arr.length; i++)  {

                    try {

                        queue2.take();

                        Helper.print(arr[i]);

                        queue1.put("OneToGo");

                    } catch (InterruptedException e)  {

                        e.printStackTrace();

                    }

                }

            }

        };

    }

    public static void main(String[] args) {

         MethodSix m = new MethodSix();

         Helper.instance.run(m.newThreadThree());

         Helper.instance.run(m.newThreadFour());

         Helper.instance.shutdown();

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值