当前位置 博文首页 > Jqcode:java实现线程间的通信

    Jqcode:java实现线程间的通信

    作者:[db:作者] 时间:2021-09-16 10:35

    本文章旨在记录java线程之间通信的使用方法(学习为主),文中涉及的代码非原创。

    来源:http://wingjay.com

    如何让两个线程同时执行?

    public class threadTest {
    
    	public static void main(String[] args) {
    		Thread A = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				printNumber("A");
    			}
    		});
    		
    		Thread B = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				printNumber("B");
    			}
    		});
    		A.start();
    		B.start();
    	}
    
    	public static void printNumber(String s) {
    		int i = 0;
    		while (i++ < 3) {
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println(s + "===print:" + i);
    		}
    	}
    }

    多次输出结果(观察下面几张图的不同点与相同点):

    ? ? ??? ? ? ?

    我们可以看出,A、B线程是同时执行的。

    如何等待一个线程执行完毕再执行另外一个?

    public class threadTest {
    
    	public static void main(String[] args) {
    		Thread A = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				printNumber("A");
    			}
    		});
    		
    		Thread B = new Thread(new Runnable() {
    			@Override
    			public void run() {
    				System.out.println("B开始等待A线程");
    				try {
    					A.join();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				printNumber("B");
    			}
    		});
    		A.start();
    		B.start();
    	}
    
    	public static void printNumber(String s) {
    		int i = 0;
    		while (i++ < 3) {
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println(s + "===print:" + i);
    		}
    	}
    }

    输出结果:

    观察结果,可以看到在B线程中先输出了一句“B开始等待A线程”,然后A线程开始执行,A线程执行完毕最后B线程开始执行,之所以会这样,因为我们加了这句代码,A.join();

    join()方法的作用是使当前的线程停止下来,等待调用的线程执行完毕后再执行自身线程。(使得线程之间的并行操作暂时改变为串行操作)

    如何让两个线程按照指定顺序交叉执行?

    如果想要按照自己定义的顺序执行线程,依赖于join()是不行的,得需要更细粒度的去控制线程的执行顺序。

    public class threadTest {
    
    	public static void main(String[] args) {
    		Object lock = new Object();
    		Thread A = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				synchronized (lock) {
    					System.out.println("A1");
    					try {
    						lock.wait();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					System.out.println("A2");
    					System.out.println("A3");
    				}
    				
    			}
    		});
    		
    		Thread B = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				synchronized(lock) {
    					System.out.println("B1");
    					System.out.println("B2");
    					System.out.println("B3");
    					lock.notify();
    				}
    			}
    		});
    		
    		A.start();
    		B.start();
    	}
    }
    

    输出结果:

    解释下输出结果:

    首先两个线程A、B共用一个对象锁,当A线程开始执行时将对象锁取走,此时B线程处于等待状态;A线程输出A1后调用方法wait(),使自身线程进入等待状态,释放对对象锁的持有权,此时B线程获得对象锁开始执行线程,分别输出B1、B2、B3,输出完毕后B线程调用notify()方法唤醒处于等待状态的A线程,A线程继续执行输出A2、A3。

    如何使一个线程等待多个线程?

    前面用到的join()方法可以使得当前线程等待其他线程,那如果需要等待多个线程该怎么办呢,我们可以用CountDownLatch。

    public class threadTest {
    
    	public static void main(String[] args) {
    		int count = 3;
    		CountDownLatch countDownLatch = new CountDownLatch(count);
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				System.out.println("当前线程为D线程,等待其他3个线程。");
    				try {
    					countDownLatch.await();
    					System.out.println("其他3个线程已执行完毕,D线程开始...");
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}).start();
    		
    		for(char threadName='A';threadName <='C';threadName++) {
    			String name= String.valueOf(threadName);
    			new Thread(new Runnable() {
    				
    				@Override
    				public void run() {
    					System.out.println(name + "线程开始执行");
    					try {
    						Thread.sleep(100);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					System.out.println(name + "线程执行完毕");
    					countDownLatch.countDown();
    				}
    			}).start();
    		}
    	}
    }
    

    CountDownLatch相当于一个计数器,首先需要给他初始化一个计数值,当其他线程执行时我们可以递减这个计数值,当这个计数值减到0时,当前线程就可以继续执行了。

    countDownLatch.await()? ?检查计数值是否为0,不为0时继续等待,为0时开始执行。

    countDownLatch.countDown()? ? 逐渐计数值,每次减。

    CountDownLatch使用于一个线程等待多个线程的场景。

    ============================================

    学习结束,以后继续学习线程相关知识。

    cs
    下一篇:没有了