最近在实际项目中遇到了需要多线程来处理的一个实际问题:一堆视频资源需要上传到一个cc平台,如果串行处理,显然不能很好实用多核的cpu处理器,于是考虑到实用线程的方式进行上传,但是创建多少个线程了?如果一个资源对应一个线程去处理,当资源数目过多的时候,创建的线程过多,同时执行处理资源显然会把服务器搞崩。经过思考,和同事进行讨论,也是同事的提醒,建议说一次性最多创建5个线程,进行对资源进行处理比较好,创建5个线程,然后这个5个线程同时去抢资源,抢到一个资源然后在进行处理,于是有了下面落地的方案:
1.线程安全的集合存放资源
- ArrayList :
- LinkedList:
- HashMap:
- HashSet:
- TreeMap:
- TreeSet:
- StringBulider:
以上都是线程不安全的,最后选择使用ConcurrentLinkedQueue,它是线程安全的集合,
允许并发的访问数据结构的不同部分来使竞争极小化。
这些集合返回弱一致性的迭代器。这意味着迭代器不一定能反映出他们被构造之后的所有的修改,但是,他们不会将同一个值返回两次。
2.多线程代码编写
- package com.lgy;
-
- import java.util.Queue;
- import java.util.concurrent.ConcurrentLinkedQueue;
-
- /**
- * Created by fengch on 2018/3/8.
- */
- public class MyTest {
-
- public static void main(String[] args) {
- final Queue<String> queue = new ConcurrentLinkedQueue<String>();
- queue.add("11111111111");
- queue.add("22222222222");
- queue.add("33333333333");
- queue.add("44444444444444");
- queue.add("555555555555555");
- queue.add("666666666666666");
- queue.add("7777777777777");
-
-
- for(int i = 0; i < 5; i++) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (queue.size() > 0) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- String value = queue.poll();
- if(value != "" && null != value)
- System.out.println(Thread.currentThread().getName() + "------------ " + value);
- }
-
-
- }
- }).start();
- }
- }
- }这种写法,既不会出现漏掉资源的情况,同时也不会出现将同一个资源同时执行的情况!
ps,如何判断创建的所以线程都执行完毕了呢?
- ExecutorService exec = Executors.newCachedThreadPool();
- final CountDownLatch endGate = new CountDownLatch(5);
这两种方式都可以实现,一种是将所以的线程放在一个线程池中,另一种是使用闭锁的方式,计数器,当计数器为0的时候,表示所以的线程都已经执行完成!