1.我们先模拟常见的问题
① 如果我们需要执行一个比较耗时的方法,并且不关心这个运行的结果,我们可以放入到线程去执行,节省时间。如发送短信之类的。、
② 多线程的执行在于并行,如果我们需要并行处理两个线程,并且要得到确定的结果,我们需要实现Callable 接口
③ 根据第②的结果,我们再进行结果汇总。
1、CountDownLatch,它是一种计数器的方式保证线程同步;它不去控制多个子线程之间的前后关系,只保证某一线程能够在这些子线程执行完成后再执行。
2、CyclicBarrier,通过设置屏障的方式使得多线程同步,能够控制多个线程在屏障处等等其他线程也执行到屏障点,可以实现CountDownLatch具有的功能,但是比CountDownLatch功能强大;
3、Semaphore,信号量,用于控制访问某一公共资源的并发线程数;
4、Exchanger,用于两个线程之间的数据交换。
先强调两个东西 wait() 和notify() 这两个方法都需要和synchronized 配合使用 表示使当前线程进行等待和唤醒
由下面的例子我们解释一下,当wait() 之后,该对象锁进入该对象的等待池中,等待被唤醒,当执行一个唤醒,就会随机唤醒一个。notifyAll() 就相当于全部唤醒 Join() 等待该线程执行完成之后再执行后续操作
先看一个示范解释 wait notify
public class MyTest1 { static class MyThead extends Thread{ private Object obj; private String name; public MyThead(String name,Object obj){ this.name = name; this.obj = obj; } @Override public void run() { synchronized (obj){ try { System.out.println("线程" + name +"----进行等待"); obj.wait(); System.out.println("线程" + name +"----线程被唤醒"); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object obj = new Object(); for(int i = 0; i < 6; i++){ new MyThead(i+"",obj).start(); } System.out.println("主线程睡觉10秒后唤醒"); Thread.sleep(10000); synchronized (obj){ obj.notify(); obj.notify(); obj.notify(); obj.notify(); } System.out.println("主线程唤醒后再睡10秒"); Thread.sleep(10000); System.out.println("主线程结束"); } }
结果
主线程睡觉10秒后唤醒 线程0----进行等待 线程1----进行等待 线程2----进行等待 线程3----进行等待 线程4----进行等待 线程5----进行等待 主线程唤醒后再睡10秒 线程0----线程被唤醒 线程3----线程被唤醒 线程2----线程被唤醒 线程1----线程被唤醒 主线程结束
The choice is arbitrary 文档上面选择是任意的,但是我没有实验出来,每次总是第一个等待的线程被唤醒,可能和线程数量有关,我们按照文档理解就行