1.CountDownLatch
List list = new ArrayList<String>();
for(int i= 0;i<100000;i++){
list.add(String.valueOf(i));
}
//System.out.println(list.toString());
int threadnum = list.size() % 200 == 0? list.size() / 200 +1 :list.size() / 200 ;
CountDownLatch countThread = new CountDownLatch(threadnum);
for(int i = 0 ; i< threadnum ; i++){
int endIndex = (i+1)*200;
int startIndex = 200 * i;
new Thread(new Runnable() {
@Override
public void run() {
try {
List subList = list.subList(startIndex, endIndex);
System.out.println(subList.toString());
}catch (Exception e){
}finally {
countThread.countDown();
}
}
}).start();
}
try {
countThread.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
CountDownLatch的构造函数接收一个 int型参数作为计数器,例如想让N任务完成之后才能继续执行,创建CountDownLatch时传入参数N;
需要等待的线程会调用CountDownLatch的await方法,该线程就会阻塞直到计数器的值减为0,而达到自己预期的线程会调用CountDownLatch的countDown()方法,计数器N的值减1。由于countDown方法可以在任何地方调用,所以计数器N既可以代表N个线程,也可以是一个线程的N个执行步骤。代表多个线程时,只需要将这个CountDownLatch的引用传到线程里面即可。
N的值为1时,退化为单一事件,即由一个线程来通知其他线程,效果等同于对象的wait和notifyAll;N为0时,调用await方法不会阻塞当前线程
这只是简化的例子 ,做某个操作的时候,我们可以用多线程批量操作,加快效率。(当我看到这段代码仿佛打开了一个新世界0-0)
2.线程池
为什么要用线程池:
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
静态方法创建线程池
- newSingleThreadExecutor
- newFixedThreadPool
- newCachedThreadPool
- newScheduledThreadPool
ExecutorService pool = Executors. newSingleThreadExecutor();
//创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
//关闭线程池
pool.shutdown();
其他方法不一一举例
参考资料:
https://www.jianshu.com/p/965ffb474d89
https://blog.csdn.net/sd0902/article/details/8395677