有一个场景需要实现多线程处理任务完毕后,再串行处理后面的流程。
下面首先介绍的方式,是通过synchronized同步锁来实现,这是一种最基础的方式,后面的文章,我整理其他其他更丰富的方法。
通过synchronized同步锁来实现:
就是放置一个公用的static变量,假如有10个线程,每个线程处理完上去累加下结果,然后后面用一个死循环(或类似线程阻塞的方法),去数这个结果,达到10个,说明大家都执行完了,就可以执行后续的事情了,这个想法虽然土鳖,但是基本上跟语言无关,几乎所有主流编程语言都支持。
下面直接上代码:
public class ThreadLockTest { public static Integer flag = 0;//公用变量 public static void main(String[] args) throws Exception { ThreadLockTest testObj = new ThreadLockTest(); final int threadNum = 10; for (int i = 0; i < threadNum; i++) { new Thread(new MyRunable(i, testObj)).start(); } while (true) { if (testObj.flag >= threadNum) { System.out.println("-----------\n所有thread执行完成!"); break; } Thread.sleep(10); } } static class MyRunable implements Runnable { int _i = 0; ThreadLockTest _test; public MyRunable(int i, ThreadLockTest test) { this._i = i; this._test = test; } @Override public void run() { try { Thread.sleep((long) (Math.random() * 10)); System.out.println("thread " + _i + " done"); //利用synchronized获得同步锁 synchronized (_test) { _test.flag += 1; } System.out.println("thread " + _i + " => " + _test.flag);//测试用 } catch (Exception e) { e.printStackTrace(); } } } }
可以看到上面使用synchronized获得同步锁的处理类似下面的代码,其中必须加上synchronized是为了证不会出现并发线程同时访问的情况。
public class Sample1 { private static Integer count = 0; synchronized public static void increment() { count++; } }
升级开始,下面再来看一段代码:
public class Sample2 { private static AtomicInteger count = new AtomicInteger(0); public static void increment() { count.getAndIncrement(); } }
上面使用AtomicInteger中却不用加上synchronized,因为AtomicInteger是一个提供原子操作的Integer类,它是通过线程安全的方式操作加减,因此十分适合高并发情况下的使用。
两相对比下来,是不是使用AtomicInteger更简单呢。下面咱就对最上面的代码,使用AtomicInteger优化调整一下,于是就有了下面的代码:
import java.util.concurrent.atomic.AtomicInteger; public class ThreadAtomTest { public static AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) throws Exception { final int threadNum = 10; for (int i = 0; i < threadNum; i++) { new Thread(new ThreadAtomTest.MyRunable(i)).start(); } while (true) { if (ThreadAtomTest.atomicInteger.intValue() >= threadNum) { System.out.println("-----------\n所有thread执行完成!"); break; } Thread.sleep(10); } } static class MyRunable implements Runnable { int _i = 0; public MyRunable(int i) { this._i = i; } @Override public void run() { try { Thread.sleep((long) (Math.random() * 10)); System.out.println("thread " + _i + " done"); int andIncrement = ThreadAtomTest.atomicInteger.incrementAndGet(); System.out.println("thread " + _i + " => " + andIncrement);//测试用 } catch (Exception e) { e.printStackTrace(); } } } }