Java线程:线程池

藏宝库编辑 2024-9-17 00:17:02 64 0 来自 中国
utils包提供开了 ExecutorService 线程池的实现,告急目标是为了重复利用线程,进步体系服从。
Thread是一个重量级的资源,创建、启动以及烧毁都是比力泯灭体系资源的,因此利用线程池来管理线程是一个非常告急的编程风俗。
1、Thread

    new Thread(new Runnable() {        @Override        public void run() {        }    }).start();直接利用 Thread 的弊端如下:

  • 每次new Thread新建对象性能差。
  • 线程缺乏统一管理,大概无穷制新建线程,相互之间竞争,及大概占用过多体系资源导致死机或oom。
  • 缺乏更多功能,如定时实行、定期实行、线程停止。
2、线程池(ExecutorService、ThreadPool)

(1)newCachedThreadPool

创建一个可缓存线程池,如果线程池长度高出处置处罚需要,可机动采取空闲线程,若无可采取,则新建线程
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();    for (int i = 0; i < 10; i++) {        final int index = i;        try {            Thread.sleep(index * 1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        cachedThreadPool.execute(new Runnable() {            @Override            public void run() {                System.out.println(index);            }        });    }    cachedThreadPool.shutdown();线程池为无穷大,当实行第二个使命时第一个使命已经完成,会复用实行第一个使命的线程,而不用每次新建线程。
(2)newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
    ExecutorService cachedThreadPool = Executors.newFixedThreadPool(5);    for (int i = 0; i < 10; i++) {        final int index = i;        try {            Thread.sleep(index * 1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        cachedThreadPool.execute(new Runnable() {            @Override            public void run() {                System.out.println(index);            }        });    }    cachedThreadPool.shutdown();这里支持的最大线程数是5, 也可以根据体系而定,获取体系可被利用的历程数
Runtime.getRuntime().availableProcessors()(3)newScheduledThreadPool

创建一个定长线程池,支持定时及周期性使命实行。
界说线程池,最大线程数是5
    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);延长实行:
    scheduledThreadPool.schedule(new Runnable() {        @Override        public void run() {            System.out.println("delay");        }    }, 3, TimeUnit.SECONDS);延长1秒,并每隔3秒定期实行
    scheduledThreadPool.scheduleAtFixedRate(new Runnable() {        @Override        public void run() {            System.out.println("delay 1 seconds, and excute every 3 seconds");        }    }, 1, 3, TimeUnit.SECONDS);关于延长实行和周期性实行我们还会想到Timer
    Timer timer = new Timer();    TimerTask timerTask = new TimerTask() {        @Override        public void run() {                    }    };    timer.schedule(timerTask, 1000, 3000);(4)newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来实行使命,包管全部使命按照指定序次(FIFO, LIFO, 优先级)实行。
    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();    for (int i = 0; i < 10; i++) {        final int index = i;        singleThreadExecutor.execute(new Runnable() {            @Override            public void run() {                try {                    System.out.println(index);                    Thread.sleep(2000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });    }Java提供的四种线程池的优点

  • 重用存在的线程,淘汰对象创建、消亡的开销,性能佳。
  • 可有用控制最大并发线程数,进步体系资源的利用率,同时制止过多资源竞争,制止堵塞。
  • 提供定时实行、定期实行、单线程、并发数控制等功能。
(5)自界说线程池

如果我们不想利用以上4种线程池,可以自界说一个线程池:
/** * 线程池 */public class DefaultPoolExecutor {    private static final ThreadFactory sThreadFactory = new ThreadFactory() {        private final AtomicInteger mCount = new AtomicInteger(1);        @Override        public Thread newThread(Runnable runnable) {            // 线程            return new Thread(runnable, "ThreadName #" + mCount.getAndIncrement());        }    };    // 可用处置处罚器的Java假造机的数量    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();    // 最大线程数(最佳线程数 = CPU_COUNT + 1)    private static final int MAX_CORE_POOL_SIZE = CPU_COUNT + 1;    //空闲时间到达 30s 时,采取空闲线程(每隔30s采取一次)    private static final long THREAD_TIMEOUT = 30L;    /**     * 新建一个线程池     * 每个线程都会斲丧大概1M的内存,利用线程池管理和复用线程     *     * @param corePoolSize 线程池巨细     * @return     */    public static ThreadPoolExecutor newDefaultPoolExecutor(int corePoolSize) {        if (corePoolSize == 0) {            return null;        }        corePoolSize = Math.min(corePoolSize, MAX_CORE_POOL_SIZE);        int maximumPoolSize = corePoolSize;        // corePoolSize: 当线程池小于corePoolSize时,新提交使命将创建一个新线程实行使命,纵然此时线程池中存在空闲线程        // 当线程池到达corePoolSize时,新提交使命将被放入workQueue中,等待线程池中使命调理实行        // 当workQueue已满,且maximumPoolSize>corePoolSize时,新提交使命会创建新线程实行使命        // 当提交使命数高出maximumPoolSize时,新提交使命由RejectedExecutionHandler处置处罚        // 当线程池中高出corePoolSize线程,空闲时间到达keepAliveTime时,关闭空闲线程        // 当设置allowCoreThreadTimeOut(true)时,线程池中线程空闲时间到达keepAliveTime也将关闭        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, THREAD_TIMEOUT,            TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(64), sThreadFactory);        threadPoolExecutor.allowCoreThreadTimeOut(true);        return threadPoolExecutor;    }}扩充:

除了execute可以实行线程池中的线程之外,submit也是可以的
submit的效果和execute是一样的,只是execute没有返回值,而submit有返回值。
(1)Future<?> submit(Runnable task)

        Future future1 = singleThreadExecutor.submit(new Runnable() {            @Override            public void run() {            }        });(2)<T> Future<T> submit(Runnable task, T result)

        Future<String> future = singleThreadExecutor.submit(new Runnable() {            @Override            public void run() {            }        }, "A");(3)<T> Future<T> submit(Callable<T> task);

    Callable callable = new Callable<String>() {        @Override        public String call() throws Exception {            return "A";        }    };

    Future<String> future = singleThreadExecutor.submit(callable);如果Future中有值的话可以通过以下代码获取
        try {            System.out.println(future.get());        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }Future的别的操纵如图
2.png [本章完...]
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-22 04:24, Processed in 0.151643 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表