zoukankan      html  css  js  c++  java
  • Java线程通讯方式

    线程间通信常用方式如下:

    l  休眠唤醒方式:

    Object的wait、notify、notifyAll

    Condition的await、signal、signalAll

    l  CountDownLatch:用于某个线程A等待若干个其他线程执行完之后,它才执行

    l  CyclicBarrier:一组线程等待至某个状态之后再全部同时执行

    l  Semaphore:用于控制对某组资源的访问权限

    Object的wait、notify、notifyAll

    public class WaitNotifyRunnable{
        private Object obj = new Object();
        private Integer i=0;
        public void odd() {
            while(i<10){
                synchronized (obj){
                    if(i%2 == 1){
                        System.out.println("奇数:"+i);
     i++;
                        obj.notify();
                    } else {
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    

      

    public void even(){
            while(i<10){
                synchronized (obj){
                    if(i%2 == 0){
                        System.out.println("偶数:"+i);
                        i++;
                        obj.notify();
                    } else {
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    }
                }
            }
        }
        public static void main(String[] args){
            final WaitNotifyRunnable runnable = new WaitNotifyRunnable();
            Thread t1 = new Thread(new Runnable() {
                public void run() {
                    runnable.odd();
                }
            }, "偶数线程");
            Thread t2 = new Thread(new Runnable() {
    public void run() {
                    runnable.even();
                }
            }, "奇数线程");
    
            t1.start();
            t2.start();
        }
    }
    

      Condition的await、signal、signalAll

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class WaitNotifyRunnable{
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        private Integer i=0;
        public void odd() {
            while(i<10){
                lock.lock();
     try{
                    if(i%2 == 1){
                        System.out.println("奇数:"+i);
                        i++;
                        condition.signal();
                    } else {
                        condition.await();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
    
            }
        }
    
        public void even(){
            while(i<10){
                lock.lock();
                try{
                    if(i%2 == 0){
                        System.out.println("偶数:"+i);
                        i++;
                        condition.signal();
                    } else {
     condition.await();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
    
            }
        }
        public static void main(String[] args){
            final WaitNotifyRunnable runnable = new WaitNotifyRunnable();
     Thread t1 = new Thread(new Runnable() {
                public void run() {
                    runnable.odd();
                }
            }, "偶数线程");
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    runnable.even();
                }
            }, "奇数线程");
    
            t1.start();
            t2.start();
        }
    }
    

      

    Object和Condition休眠唤醒区别

    l  object wait()必须在synchronized(同步锁)下使用,

    l  object wait()必须要通过Nodify()方法进行唤醒

    l  condition await() 必须和Lock(互斥锁/共享锁)配合使用

    l  condition await() 必须通过 signal() 方法进行唤醒

      CountDownLatch方式

    CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。

    CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量

     每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务

    import java.util.concurrent.CountDownLatch;
    
    public class CoachRecerDemo {
    	private CountDownLatch countDownLatch=new CountDownLatch(3); //设置要等待的运动员
    	//运动员方法
    	public void racer(){
    		//获取线程名
    		String name=Thread.currentThread().getName();
    		System.out.println(name+"正在准备....");
    		try {
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(name+"准备完毕");
    		countDownLatch.countDown();//-1
    	}
    	//教练方法
    	public void coach(){
    		String name=Thread.currentThread().getName();
    		System.out.println(name+"等待运动员准备...");
    		try {
    			countDownLatch.await();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println("所有运动员就绪,"+name+"开始训练");
    	}
    
    	public static void main(String[] args) {
    		//1.创建CoachRecerDemo 实例
    		CoachRecerDemo coachRecerDemo=new CoachRecerDemo();
    		//2.创建三个线程对象
    		Thread thread1=new Thread(new Runnable(){
    			public void run() {
    				coachRecerDemo.racer();
    			}
    		},"运动员1");
    		
    		Thread thread2=new Thread(new Runnable() {
    			public void run() {
    				coachRecerDemo.racer();
    			}
    		},"运动员2");
    		
    		Thread thread3=new Thread(new Runnable() {
    			public void run() {
    				coachRecerDemo.racer();
    			}
    		},"运动员3");
    		
    		//3.教练
    		Thread thread4=new Thread(new Runnable() {
    			public void run() {
    				coachRecerDemo.coach();
    				
    			}
    		},"教练");
    		
    		thread4.start();
    		thread1.start();
    		thread2.start();
    		thread3.start();
    	}
    }
    

       CyclicBarrier方式

    CyclicBarrier是在java1.5被引入的,存在于java.util.concurrent包下。

    CyclicBarrier实现让一组线程等待至某个状态之后再全部同时执行。

    CyclicBarrier底层是三个线程同时启动

    import java.util.Date;
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    public class ThreeThreadStartDemo {
    	private CyclicBarrier cyclicBarrier = new CyclicBarrier(3);// 所有参与启动的线程数
    
    	public void startThread() {
    		// 打印线程准备启动
    		String name = Thread.currentThread().getName();
    		System.out.println(name + "正在准备...");
    
    		// 2.调用CyclicBarriar的await方法等待线程准备完毕
    		try {
    			cyclicBarrier.await();
    		} catch (InterruptedException | BrokenBarrierException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    		// 3.打印线程启动信息
    		System.out.println(name + "已经启动完毕" + new Date().getTime());
    
    	}
    
    	public static void main(String[] args) {
    		final ThreeThreadStartDemo threadStartDemo = new ThreeThreadStartDemo();
    		Thread thread1 = new Thread(new Runnable() {
    			public void run() {
    
    				threadStartDemo.startThread();
    			}
    		});
    		Thread thread2 = new Thread(new Runnable() {
    			public void run() {
    
    				threadStartDemo.startThread();
    			}
    		});
    		Thread thread3 = new Thread(new Runnable() {
    			public void run() {
    
    				threadStartDemo.startThread();
    			}
    		});
    		
    		thread1.start();
    		thread2.start();
    		thread3.start();
    	}	
    }
    

      Semaphore方式

    Semaphore是在java1.5被引入的,存在于java.util.concurrent包下。

    Semaphore用于控制对某组资源的访问权限。

    import java.util.concurrent.Semaphore;
    
    public class WorkerMachineDemo {
    	static class Work implements Runnable {
    		private int workerNum;
    		private Semaphore semaphore;
    
    		public Work(int workerNum, Semaphore semaphore) {
    			this.workerNum = workerNum;
    			this.semaphore = semaphore;
    		}
    
    		public void run() {
    			// 1.获取机器
    			// 2.打印工人获取到机器,开始工作
    			// 3.线程睡眠1000毫秒
    			// 4.使用完毕
    			try {
    				semaphore.acquire();
    				String name = Thread.currentThread().getName();
    				System.out.println(name + "获取到机器,开始工作");
    				Thread.sleep(1000);
    				semaphore.release();
    				System.out.println(name + "使用完毕,释放机器!");
    			} catch (Exception e) {
    				// TODO: handle exception
    			}
    		
    		}
    	}
    
    	public static void main(String[] args) {
    		int works = 8;
    		Semaphore semaphore = new Semaphore(3);// 机器数
    		for (int i = 0; i < works; i++) {
    
    			new Thread(new Work(i, semaphore)).start();
    		}
    
    	}
    }
    

      sleep和wait区别:

      wait和notify区别

    wait和notify都是Object中的方法

    wait和notify执行前线程都必须获得对象锁

    wait的作用是使当前线程进行等待

    notify的作用是通知其他等待当前线程的对象锁的线程

  • 相关阅读:
    lambda表达式
    解读Raft(一 算法基础)
    译《Time, Clocks, and the Ordering of Events in a Distributed System》
    如何在MQ中实现支持任意延迟的消息?
    读Kafka Consumer源码
    2017上海QCon之旅总结(下)
    2017上海QCon之旅总结(中)
    2017上海QCon之旅总结(上)
    什么是WAL?
    Push or Pull?
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/12188289.html
Copyright © 2011-2022 走看看