线程间的通信

线程间的通信

  1. 常用的 wait()、notify()、notifyAll();在一个线程里面,唤醒其他拥有同样的锁的线程
/**
 * 使用wait(),notify(),notifyAll()时,代码块必须上锁
 * @author : fzz
*/
public class Communicate {
 private static Object lock = new Object();
 private static String str = null;
 public static void main(String[] args) {

     new Thread(()->{
         synchronized(lock) {
             System.out.println(Thread.currentThread().getName() + "准备就绪!");
             try {
                 lock.wait();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println(Thread.currentThread().getName() + ":  " + str);
         }
     }).start();
     new Thread(()->{
         synchronized(lock) {
             System.out.println(Thread.currentThread().getName() + "准备写入!");
             str = "fzz";
             System.out.println(Thread.currentThread().getName() + "写入完成: str = " + str);
             try {
                 lock.notify();
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }).start();
 }
}
  1. Piped管道,通过管道字节流,实现线程间的数据交换
/**
 * @author : fzz
*/
public class PipedReader implements Runnable{

 private PipedInputStream pipedInputStream;

 public PipedReader(PipedInputStream pipedInputStream) {
     this.pipedInputStream = pipedInputStream;
 }

 @Override
 public void run() {
     if (pipedInputStream!=null) {
         // 读取数据,以\n 结束
         String collect = new BufferedReader(new InputStreamReader(pipedInputStream)).lines().collect(Collectors.joining("\n"));
         System.out.println("Reader:"+collect);
         try {
             pipedInputStream.close();
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
 }
}


/**
 * @author : fzz
*/
public class PipedDemo {

 public static void main(String[] args) throws Exception {
     PipedInputStream pipedInputStream = new PipedInputStream();
     PipedOutputStream pipedOutputStream = new PipedOutputStream();
     //创建管道
     pipedOutputStream.connect(pipedInputStream);
     new Thread(new PipedReader(pipedInputStream)).start();
     BufferedReader br;
     try{
         //读取数据
         br = new BufferedReader(new InputStreamReader(System.in));
         pipedOutputStream.write(br.readLine().getBytes());
     }finally {
         pipedOutputStream.close();
     }
 }

}
  1. Thread.join()方法;在A线程内调用启动B线程,等待B线程执行完成,A线程再继续运行
/**
 * @author : fzz
*/
public class CommunicateDemo {
 public static void main(String[] args) {
     Thread thread = new Thread(() -> {
         System.out.println("我是线程1,我被调用了!");
     }, "线程1");
     new Thread(() -> {
         System.out.println(Thread.currentThread().getName()+"准备调用 线程1");
         thread.start();
         try {
             thread.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println(Thread.currentThread().getName()+"调用线程1 完成!");
     }, "线程2").start();
 }
}
  1. 通过ThreadLocal实现,当前线程拥有自己的实例,互不干扰;ThreadLocal 底层用一个Map结构

    key:当前线程 value:当前线程存放的值

/**
 * @author : fzz
*/
public class ThreadLocalDemo {
 private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->0);

 public void inCreate(){
     Integer num = threadLocal.get();
     num++;
     System.out.println(Thread.currentThread().getName()+"====》"+ num);
     threadLocal.set(num);
 }

 public static void main(String[] args) {
     ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo();
     for (int i = 0; i < 3; i++) {
         //每个线程自己本地都有一份threadLocal,线程之间不会影响
         new Thread(()->{
             while(true){
                 threadLocalDemo.inCreate();
                 try {
                     Thread.sleep(3000L);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }

         }).start();
     }
 }
}
打印结果:
Thread-0====1
Thread-1====1
Thread-2====1
Thread-0====2
Thread-2====2
Thread-1====2
Thread-1====3
Thread-0====3
Thread-2====3
Thread-2====4
Thread-1====4
Thread-0====4

  1. ,Condition实现(相比 wait,notify() 可以有多的等待,唤醒,通过newCondition,指定性强)
/**
 * @author : fzz
 */
public class ConfitionDemo {
    static Lock lock = new ReentrantLock();
    static String str = null;
    static Condition condition = lock.newCondition();

    public static void main(String[] args) {

        new Thread(()->{
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "准备就绪!");
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":  " + str);
            lock.unlock();
        }).start();
        new Thread(()->{
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "准备写入!");
            str = "fzz";
            System.out.println(Thread.currentThread().getName() + "写入完成: str = " + str);
            try {
                condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            }
            lock.unlock();
        }).start();
    }
}

  1. CountDownLatch:通过countDown计数减一,调用 await() 等待所有线程执行完成再继续
/**
 * @author : fzz
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws Exception{
        //如果没有用countDownLatch 运行结束可能在中间打印
        CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+":"+ finalI);
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("运行结束!");
    }

}
//        用CountDownLatch:       没用CountDownLatch:
//        Thread-0:0              Thread-0:0
//        Thread-7:7              Thread-7:7
//        Thread-8:8              Thread-8:8
//        Thread-6:6              Thread-6:6
//        Thread-5:5              运行结束!
//        Thread-4:4              Thread-4:4
//        Thread-3:3              Thread-3:3
//        Thread-1:1              Thread-1:1
//        Thread-2:2              Thread-2:2
//        Thread-9:9              Thread-9:9
//        运行结束!                Thread-5:5

  1. CyclicBarrier:多个线程等到同一状态,一起运行
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(()->{
                try {
                    Thread.sleep(finalI *1000L);
                    System.out.println(Thread.currentThread().getName()+"准备就绪!");
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"开始!");
            }).start();
        }
    }
}
//    Thread-0准备就绪!
//    Thread-1准备就绪!
//    Thread-2准备就绪!
//    Thread-3准备就绪!
//    Thread-4准备就绪!
//    Thread-4开始!
//    Thread-0开始!
//    Thread-1开始!
//    Thread-2开始!
//    Thread-3开始!

  1. semaphore信号量:起到一个限流的作用,只允许几个线程运行
public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        for (int i = 0; i < 5; i++) {
            new Thread(()->{
                try{
                    //占用
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(3000L);
                }catch (Exception e){
                    e.printStackTrace();
                } finally{
                    //释放
                    semaphore.release();
                }
            }).start();
        }
    }
}
  1. Exchanger(成对使用):用于交换数据,当两个线程都达到exchanger时候,交换数据;否则一直等待
public class ExchangerDemo {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        String str1 = "hello";
        String str2 = "world";
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"初始化值===>"+str1);
            try {
                //交换后的返回值
                String exchange = exchanger.exchange(str1);
                System.out.println(Thread.currentThread().getName()+"交换后值===>"+exchange);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"线程一").start();

        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"初始化值===>"+str2);
            try {
                //交换后的返回值
                String exchange = exchanger.exchange(str2);
                System.out.println(Thread.currentThread().getName()+"交换后值===>"+exchange);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"线程二").start();
    }
}
线程一初始化值===>hello
线程二初始化值===>world
线程二交换后值===>hello
线程一交换后值===>world

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值