美文网首页
如何更好的使用线程

如何更好的使用线程

作者: 多与少 | 来源:发表于2020-09-07 15:33 被阅读0次

    一、线程的创建

    目前有以下四种方式创建线程:

    1. 继承Thread类
    package com.fuping.liuqu.demo.thread;
    
    public class CustomizeThread extends Thread{
    
        @Override
        public synchronized void start() {
            super.start();
        }
    
        @Override
        public void run() {
            super.run();
        }
    }
    
    1. 实现Runnable类
    package com.fuping.liuqu.demo.thread;
    
    public class CustomizeRunnable implements Runnable {
        @Override
        public void run() {
    
        }
    }
    
    1. 实现Callable类
    package com.fuping.liuqu.demo.thread;
    
    import java.util.concurrent.*;
    
    public class CustomizeCallable implements Callable<Future<String>> {
        @Override
        public Future<String> call() throws Exception {
            return new Future<String>() {
                @Override
                public boolean cancel(boolean mayInterruptIfRunning) {
                    return false;
                }
    
                @Override
                public boolean isCancelled() {
                    return false;
                }
    
                @Override
                public boolean isDone() {
                    return false;
                }
    
                @Override
                public String get() throws InterruptedException, ExecutionException {
                    return "STW";
                }
    
                @Override
                public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
                    return null;
                }
            };
        }
    }
    
    
    1. 通过线程池创建线程
    package com.fuping.liuqu.demo.thread;
    
    import java.util.concurrent.*;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class CustomizeThreadPool {
        public static void main(String[] args) {
            int corePoolSize = 5;
            int maximumPoolSize = 5;
            long keepAliveTime = 20000L;
            TimeUnit unit = TimeUnit.MINUTES;
            BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();
            RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
            ThreadGroup threadGroup = new ThreadGroup("manas-dataset");
            ThreadFactory threadFactory = new ThreadFactory() {
                final AtomicInteger atomicInteger = new AtomicInteger(0);
    
                @Override
                public Thread newThread(Runnable runnable) {
                    return new Thread(threadGroup, runnable, "Thread-DataSet" + atomicInteger.incrementAndGet());
                }
            };
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
                    maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
            threadPoolExecutor.submit(CustomizeThreadPool::print);
        }
    
        private static void print() {
            System.out.println("STW");
        }
    }
    
    

    注意:

    • 线程组、线程的命名,好的命名可以帮助开发、运维人员定位问题
    • corePoolSize、maximumPoolSize的设置,需要考虑到IO、CPU核数,设置合适的参数可以提高程序的性能。
    • 通过线程池访问外部接口时,需要注意对外部接口造成的并发,可通过如下代码在多线程时生成的随机数,控制并发
    package com.fuping.liuqu.demo.thread;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.concurrent.*;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class CustomizeThreadPool {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(CustomizeThreadPool.class);
    
        public static void main(String[] args) {
            int corePoolSize = 5;
            int maximumPoolSize = 5;
            long keepAliveTime = 20000L;
            TimeUnit unit = TimeUnit.MINUTES;
            BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();
            RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
            ThreadGroup threadGroup = new ThreadGroup("manas-dataset");
            ThreadFactory threadFactory = new ThreadFactory() {
                final AtomicInteger atomicInteger = new AtomicInteger(0);
    
                @Override
                public Thread newThread(Runnable runnable) {
                    final int randomInt = ThreadLocalRandom.current().nextInt();
                    String threadName = "Thread-DataSet" + atomicInteger.incrementAndGet();
                    try {
                        TimeUnit.MILLISECONDS.sleep(randomInt);
                    } catch (InterruptedException e) {
                        LOGGER.warn("threadName start failed,msg is {}", e.getMessage());
                    }
                    return new Thread(threadGroup, runnable, threadName);
                }
            };
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
                    maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
            for (int i = 0; i < 10; i++) {
                threadPoolExecutor.submit(CustomizeThreadPool::print);
            }
        }
    
        private static void print() {
            System.out.println("STW");
        }
    }
    
    
    • 根据业务选择合适的队列
    • 根据业务选择饱和策略

    二、队列的选择

    JDK中相关的数据结构如下

    BlockingQueue、BlockingDeque
    LinkedBlockingQueue               无界队列,注意OOM,注意最大线程数的陷阱, Executors.newFixedThreadPool()的底层队列,Executors.newSingleThreadExecutor()的底层队列
    ArrayBlockingQueue                有界队列,注意OOM
    DelayQueue                        延迟队列,Redis底层实现的队列
    DelayedWorkQueue                  JDK内部实现队列,Executors.newScheduledThreadPool()底层实现队列
    PriorityQueue                     优先级队列,可自定义排序,默认自然排序
    PriorityBlockingQueue             优先级阻塞队列
    ConcurrentSkipListMap             跳跃表Map,查询快
    ConcurrentSkipListSet             跳跃表Set
    ConcurrentLinkedMap               同步的链表Map
    CopyOnWriteArrayList              写入时复制数组List,类似于Linux底层的Copy-On-Write技术,例如配置、黑名单、物流地址等变化非常少的数据,这是一种无锁的实现。可以帮我们实现程序更高的并发。可参考学习:https://baijiahao.baidu.com/s?id=1636057331750965212&wfr=spider&for=pc
    CopyOnWriteArraySet               写入时复制数组Set
    TransferQueue                     抢占式队列,分公平式与非公平式,默认非公平
    SychronousQueue                   同步队列,Executors.newCachedThreadPool()的底层实现队列
    TreeMap                           有序Map
    TreeSet                           有序Set 
    

    三、饱和策略的选择

    JDK提供了四种原生的饱和拒绝执行策略,当然也可以自定义饱和拒绝策略

        /**
         * A handler for rejected tasks that runs the rejected task
         * directly in the calling thread of the {@code execute} method,
         * unless the executor has been shut down, in which case the task
         * is discarded.
         */
        public static class CallerRunsPolicy implements RejectedExecutionHandler {
            /**
             * Creates a {@code CallerRunsPolicy}.
             */
            public CallerRunsPolicy() { }
    
            /**
             * Executes task r in the caller's thread, unless the executor
             * has been shut down, in which case the task is discarded.
             *
             * @param r the runnable task requested to be executed
             * @param e the executor attempting to execute this task
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    r.run();
                }
            }
        }
    
        /**
         * A handler for rejected tasks that throws a
         * {@code RejectedExecutionException}.
         */
        public static class AbortPolicy implements RejectedExecutionHandler {
            /**
             * Creates an {@code AbortPolicy}.
             */
            public AbortPolicy() { }
    
            /**
             * Always throws RejectedExecutionException.
             *
             * @param r the runnable task requested to be executed
             * @param e the executor attempting to execute this task
             * @throws RejectedExecutionException always
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                throw new RejectedExecutionException("Task " + r.toString() +
                                                     " rejected from " +
                                                     e.toString());
            }
        }
    
        /**
         * A handler for rejected tasks that silently discards the
         * rejected task.
         */
        public static class DiscardPolicy implements RejectedExecutionHandler {
            /**
             * Creates a {@code DiscardPolicy}.
             */
            public DiscardPolicy() { }
    
            /**
             * Does nothing, which has the effect of discarding task r.
             *
             * @param r the runnable task requested to be executed
             * @param e the executor attempting to execute this task
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            }
        }
    
        /**
         * A handler for rejected tasks that discards the oldest unhandled
         * request and then retries {@code execute}, unless the executor
         * is shut down, in which case the task is discarded.
         */
        public static class DiscardOldestPolicy implements RejectedExecutionHandler {
            /**
             * Creates a {@code DiscardOldestPolicy} for the given executor.
             */
            public DiscardOldestPolicy() { }
    
            /**
             * Obtains and ignores the next task that the executor
             * would otherwise execute, if one is immediately available,
             * and then retries execution of task r, unless the executor
             * is shut down, in which case task r is instead discarded.
             *
             * @param r the runnable task requested to be executed
             * @param e the executor attempting to execute this task
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    e.getQueue().poll();
                    e.execute(r);
                }
            }
        }
    

    四、线程执行

    在线程池创建时,可通过执行以下方法,将所有的核心线程预先启动

        /**
         * Starts all core threads, causing them to idly wait for work. This
         * overrides the default policy of starting core threads only when
         * new tasks are executed.
         *
         * @return the number of threads started
         */
        public int prestartAllCoreThreads() {
            int n = 0;
            while (addWorker(null, true))
                ++n;
            return n;
        }
    

    在线程池中有beforeExecute()、afterExecute()、terminated()三个方法,分别代表线程执行前、线程执行后、线程执行完。实现自定义线程池,然后通过重写此三个方法,可以做些统计类或者操作类的操作。

        /**
         * Method invoked prior to executing the given Runnable in the
         * given thread.  This method is invoked by thread {@code t} that
         * will execute task {@code r}, and may be used to re-initialize
         * ThreadLocals, or to perform logging.
         *
         * <p>This implementation does nothing, but may be customized in
         * subclasses. Note: To properly nest multiple overridings, subclasses
         * should generally invoke {@code super.beforeExecute} at the end of
         * this method.
         *
         * @param t the thread that will run task {@code r}
         * @param r the task that will be executed
         */
        protected void beforeExecute(Thread t, Runnable r) { }
    
        /**
         * Method invoked upon completion of execution of the given Runnable.
         * This method is invoked by the thread that executed the task. If
         * non-null, the Throwable is the uncaught {@code RuntimeException}
         * or {@code Error} that caused execution to terminate abruptly.
         *
         * <p>This implementation does nothing, but may be customized in
         * subclasses. Note: To properly nest multiple overridings, subclasses
         * should generally invoke {@code super.afterExecute} at the
         * beginning of this method.
         *
         * <p><b>Note:</b> When actions are enclosed in tasks (such as
         * {@link FutureTask}) either explicitly or via methods such as
         * {@code submit}, these task objects catch and maintain
         * computational exceptions, and so they do not cause abrupt
         * termination, and the internal exceptions are <em>not</em>
         * passed to this method. If you would like to trap both kinds of
         * failures in this method, you can further probe for such cases,
         * as in this sample subclass that prints either the direct cause
         * or the underlying exception if a task has been aborted:
         *
         *  <pre> {@code
         * class ExtendedExecutor extends ThreadPoolExecutor {
         *   // ...
         *   protected void afterExecute(Runnable r, Throwable t) {
         *     super.afterExecute(r, t);
         *     if (t == null && r instanceof Future<?>) {
         *       try {
         *         Object result = ((Future<?>) r).get();
         *       } catch (CancellationException ce) {
         *           t = ce;
         *       } catch (ExecutionException ee) {
         *           t = ee.getCause();
         *       } catch (InterruptedException ie) {
         *           Thread.currentThread().interrupt(); // ignore/reset
         *       }
         *     }
         *     if (t != null)
         *       System.out.println(t);
         *   }
         * }}</pre>
         *
         * @param r the runnable that has completed
         * @param t the exception that caused termination, or null if
         * execution completed normally
         */
        protected void afterExecute(Runnable r, Throwable t) { }
    
        /**
         * Method invoked when the Executor has terminated.  Default
         * implementation does nothing. Note: To properly nest multiple
         * overridings, subclasses should generally invoke
         * {@code super.terminated} within this method.
         */
        protected void terminated() { }
    

    可以设置核心线程空闲超时时间

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
            maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        // 设置使核心线程空闲时间超过keepAliveTime时间也被回收,这样线程池没有任务执行最终会自动销毁
        threadPoolExecutor.allowCoreThreadTimeOut(true);    
    
        /**
         * Returns true if this pool allows core threads to time out and
         * terminate if no tasks arrive within the keepAlive time, being
         * replaced if needed when new tasks arrive. When true, the same
         * keep-alive policy applying to non-core threads applies also to
         * core threads. When false (the default), core threads are never
         * terminated due to lack of incoming tasks.
         *
         * @return {@code true} if core threads are allowed to time out,
         *         else {@code false}
         *
         * @since 1.6
         */
        public boolean allowsCoreThreadTimeOut() {
            return allowCoreThreadTimeOut;
        }
    
        /**
         * Sets the policy governing whether core threads may time out and
         * terminate if no tasks arrive within the keep-alive time, being
         * replaced if needed when new tasks arrive. When false, core
         * threads are never terminated due to lack of incoming
         * tasks. When true, the same keep-alive policy applying to
         * non-core threads applies also to core threads. To avoid
         * continual thread replacement, the keep-alive time must be
         * greater than zero when setting {@code true}. This method
         * should in general be called before the pool is actively used.
         *
         * @param value {@code true} if should time out, else {@code false}
         * @throws IllegalArgumentException if value is {@code true}
         *         and the current keep-alive time is not greater than zero
         *
         * @since 1.6
         */
        public void allowCoreThreadTimeOut(boolean value) {
            if (value && keepAliveTime <= 0)
                throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
            if (value != allowCoreThreadTimeOut) {
                allowCoreThreadTimeOut = value;
                if (value)
                    interruptIdleWorkers();
            }
        }
    

    五、线程的关闭

    线程关闭的方法有以下两种,shutdown() 在执行后会将当前执行的任务执行完成再销毁线程池,而shutdownNow()方法会将当前执行的任务直接放弃掉,并且销毁线程池。

    
        /**
         * Initiates an orderly shutdown in which previously submitted
         * tasks are executed, but no new tasks will be accepted.
         * Invocation has no additional effect if already shut down.
         *
         * <p>This method does not wait for previously submitted tasks to
         * complete execution.  Use {@link #awaitTermination awaitTermination}
         * to do that.
         *
         * @throws SecurityException {@inheritDoc}
         */
        public void shutdown() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                checkShutdownAccess();
                advanceRunState(SHUTDOWN);
                interruptIdleWorkers();
                onShutdown(); // hook for ScheduledThreadPoolExecutor
            } finally {
                mainLock.unlock();
            }
            tryTerminate();
        }
    
        /**
         * Attempts to stop all actively executing tasks, halts the
         * processing of waiting tasks, and returns a list of the tasks
         * that were awaiting execution. These tasks are drained (removed)
         * from the task queue upon return from this method.
         *
         * <p>This method does not wait for actively executing tasks to
         * terminate.  Use {@link #awaitTermination awaitTermination} to
         * do that.
         *
         * <p>There are no guarantees beyond best-effort attempts to stop
         * processing actively executing tasks.  This implementation
         * cancels tasks via {@link Thread#interrupt}, so any task that
         * fails to respond to interrupts may never terminate.
         *
         * @throws SecurityException {@inheritDoc}
         */
        public List<Runnable> shutdownNow() {
            List<Runnable> tasks;
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                checkShutdownAccess();
                advanceRunState(STOP);
                interruptWorkers();
                tasks = drainQueue();
            } finally {
                mainLock.unlock();
            }
            tryTerminate();
            return tasks;
        }
    
    

    查看线程池的状态

    
        public boolean isShutdown() {
            return ! isRunning(ctl.get());
        }
    
        /**
         * Returns true if this executor is in the process of terminating
         * after {@link #shutdown} or {@link #shutdownNow} but has not
         * completely terminated.  This method may be useful for
         * debugging. A return of {@code true} reported a sufficient
         * period after shutdown may indicate that submitted tasks have
         * ignored or suppressed interruption, causing this executor not
         * to properly terminate.
         *
         * @return {@code true} if terminating but not yet terminated
         */
        public boolean isTerminating() {
            int c = ctl.get();
            return ! isRunning(c) && runStateLessThan(c, TERMINATED);
        }
    
        public boolean isTerminated() {
            return runStateAtLeast(ctl.get(), TERMINATED);
        }
    
    

    线程共定义了六种状态

        /**
         * A thread state.  A thread can be in one of the following states:
         * <ul>
         * <li>{@link #NEW}<br>
         *     A thread that has not yet started is in this state.
         *     </li>
         * <li>{@link #RUNNABLE}<br>
         *     A thread executing in the Java virtual machine is in this state.
         *     </li>
         * <li>{@link #BLOCKED}<br>
         *     A thread that is blocked waiting for a monitor lock
         *     is in this state.
         *     </li>
         * <li>{@link #WAITING}<br>
         *     A thread that is waiting indefinitely for another thread to
         *     perform a particular action is in this state.
         *     </li>
         * <li>{@link #TIMED_WAITING}<br>
         *     A thread that is waiting for another thread to perform an action
         *     for up to a specified waiting time is in this state.
         *     </li>
         * <li>{@link #TERMINATED}<br>
         *     A thread that has exited is in this state.
         *     </li>
         * </ul>
         *
         * <p>
         * A thread can be in only one state at a given point in time.
         * These states are virtual machine states which do not reflect
         * any operating system thread states.
         *
         * @since   1.5
         * @see #getState
         */
        public enum State {
            /**
             * Thread state for a thread which has not yet started.
             */
            NEW,
    
            /**
             * Thread state for a runnable thread.  A thread in the runnable
             * state is executing in the Java virtual machine but it may
             * be waiting for other resources from the operating system
             * such as processor.
             */
            RUNNABLE,
    
            /**
             * Thread state for a thread blocked waiting for a monitor lock.
             * A thread in the blocked state is waiting for a monitor lock
             * to enter a synchronized block/method or
             * reenter a synchronized block/method after calling
             * {@link Object#wait() Object.wait}.
             */
            BLOCKED,
    
            /**
             * Thread state for a waiting thread.
             * A thread is in the waiting state due to calling one of the
             * following methods:
             * <ul>
             *   <li>{@link Object#wait() Object.wait} with no timeout</li>
             *   <li>{@link #join() Thread.join} with no timeout</li>
             *   <li>{@link LockSupport#park() LockSupport.park}</li>
             * </ul>
             *
             * <p>A thread in the waiting state is waiting for another thread to
             * perform a particular action.
             *
             * For example, a thread that has called <tt>Object.wait()</tt>
             * on an object is waiting for another thread to call
             * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
             * that object. A thread that has called <tt>Thread.join()</tt>
             * is waiting for a specified thread to terminate.
             */
            WAITING,
    
            /**
             * Thread state for a waiting thread with a specified waiting time.
             * A thread is in the timed waiting state due to calling one of
             * the following methods with a specified positive waiting time:
             * <ul>
             *   <li>{@link #sleep Thread.sleep}</li>
             *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
             *   <li>{@link #join(long) Thread.join} with timeout</li>
             *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
             *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
             * </ul>
             */
            TIMED_WAITING,
    
            /**
             * Thread state for a terminated thread.
             * The thread has completed execution.
             */
            TERMINATED;
        }
    

    六、线程结果

    通过线程池提交线程后,会有线程的返回值Future对象,线程池是异步执行的

    Future<?> threadFuture = threadPoolExecutor.submit(CustomizeThreadPool::print);
    

    通过执行以下方法可以取消正在运行的线程

    boolean cancel(boolean mayInterruptIfRunning);
    

    通过执行以下方法判断任务是否被取消

    boolean isCancelled();
    

    通过执行以下方法判断线程是否执行完成

    boolean isDone();
    

    通过执行以下方法获取线程的返回值,前提是传入的线程类型是Callable类型

        V get() throws InterruptedException, ExecutionException;
    

    通过执行以下方法获取线程的返回值,并带超时机制,前提是传入的线程类型是Callable类型

        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    
    /*
     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     *
     * This code is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License version 2 only, as
     * published by the Free Software Foundation.  Oracle designates this
     * particular file as subject to the "Classpath" exception as provided
     * by Oracle in the LICENSE file that accompanied this code.
     *
     * This code is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     * version 2 for more details (a copy is included in the LICENSE file that
     * accompanied this code).
     *
     * You should have received a copy of the GNU General Public License version
     * 2 along with this work; if not, write to the Free Software Foundation,
     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     *
     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     * or visit www.oracle.com if you need additional information or have any
     * questions.
     */
    
    /*
     * This file is available under and governed by the GNU General Public
     * License version 2 only, as published by the Free Software Foundation.
     * However, the following notice accompanied the original version of this
     * file:
     *
     * Written by Doug Lea with assistance from members of JCP JSR-166
     * Expert Group and released to the public domain, as explained at
     * http://creativecommons.org/publicdomain/zero/1.0/
     */
    
    package java.util.concurrent;
    
    /**
     * A {@code Future} represents the result of an asynchronous
     * computation.  Methods are provided to check if the computation is
     * complete, to wait for its completion, and to retrieve the result of
     * the computation.  The result can only be retrieved using method
     * {@code get} when the computation has completed, blocking if
     * necessary until it is ready.  Cancellation is performed by the
     * {@code cancel} method.  Additional methods are provided to
     * determine if the task completed normally or was cancelled. Once a
     * computation has completed, the computation cannot be cancelled.
     * If you would like to use a {@code Future} for the sake
     * of cancellability but not provide a usable result, you can
     * declare types of the form {@code Future<?>} and
     * return {@code null} as a result of the underlying task.
     *
     * <p>
     * <b>Sample Usage</b> (Note that the following classes are all
     * made-up.)
     * <pre> {@code
     * interface ArchiveSearcher { String search(String target); }
     * class App {
     *   ExecutorService executor = ...
     *   ArchiveSearcher searcher = ...
     *   void showSearch(final String target)
     *       throws InterruptedException {
     *     Future<String> future
     *       = executor.submit(new Callable<String>() {
     *         public String call() {
     *             return searcher.search(target);
     *         }});
     *     displayOtherThings(); // do other things while searching
     *     try {
     *       displayText(future.get()); // use future
     *     } catch (ExecutionException ex) { cleanup(); return; }
     *   }
     * }}</pre>
     *
     * The {@link FutureTask} class is an implementation of {@code Future} that
     * implements {@code Runnable}, and so may be executed by an {@code Executor}.
     * For example, the above construction with {@code submit} could be replaced by:
     *  <pre> {@code
     * FutureTask<String> future =
     *   new FutureTask<String>(new Callable<String>() {
     *     public String call() {
     *       return searcher.search(target);
     *   }});
     * executor.execute(future);}</pre>
     *
     * <p>Memory consistency effects: Actions taken by the asynchronous computation
     * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
     * actions following the corresponding {@code Future.get()} in another thread.
     *
     * @see FutureTask
     * @see Executor
     * @since 1.5
     * @author Doug Lea
     * @param <V> The result type returned by this Future's {@code get} method
     */
    public interface Future<V> {
    
        /**
         * Attempts to cancel execution of this task.  This attempt will
         * fail if the task has already completed, has already been cancelled,
         * or could not be cancelled for some other reason. If successful,
         * and this task has not started when {@code cancel} is called,
         * this task should never run.  If the task has already started,
         * then the {@code mayInterruptIfRunning} parameter determines
         * whether the thread executing this task should be interrupted in
         * an attempt to stop the task.
         *
         * <p>After this method returns, subsequent calls to {@link #isDone} will
         * always return {@code true}.  Subsequent calls to {@link #isCancelled}
         * will always return {@code true} if this method returned {@code true}.
         *
         * @param mayInterruptIfRunning {@code true} if the thread executing this
         * task should be interrupted; otherwise, in-progress tasks are allowed
         * to complete
         * @return {@code false} if the task could not be cancelled,
         * typically because it has already completed normally;
         * {@code true} otherwise
         */
        boolean cancel(boolean mayInterruptIfRunning);
    
        /**
         * Returns {@code true} if this task was cancelled before it completed
         * normally.
         *
         * @return {@code true} if this task was cancelled before it completed
         */
        boolean isCancelled();
    
        /**
         * Returns {@code true} if this task completed.
         *
         * Completion may be due to normal termination, an exception, or
         * cancellation -- in all of these cases, this method will return
         * {@code true}.
         *
         * @return {@code true} if this task completed
         */
        boolean isDone();
    
        /**
         * Waits if necessary for the computation to complete, and then
         * retrieves its result.
         *
         * @return the computed result
         * @throws CancellationException if the computation was cancelled
         * @throws ExecutionException if the computation threw an
         * exception
         * @throws InterruptedException if the current thread was interrupted
         * while waiting
         */
        V get() throws InterruptedException, ExecutionException;
    
        /**
         * Waits if necessary for at most the given time for the computation
         * to complete, and then retrieves its result, if available.
         *
         * @param timeout the maximum time to wait
         * @param unit the time unit of the timeout argument
         * @return the computed result
         * @throws CancellationException if the computation was cancelled
         * @throws ExecutionException if the computation threw an
         * exception
         * @throws InterruptedException if the current thread was interrupted
         * while waiting
         * @throws TimeoutException if the wait timed out
         */
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    
    

    七、线程相关的问题

    • 线程创建,未销毁,例如隔5分钟重新创建一次线程池,那就会导致大量的线程并未销毁,会生成大量的time_wait
    • 线程创建未自定义名称,服务中大量的创建各种线程,导致无法快速的定位问题
    • 线程数超过限制,大量创建线程达到系统的限制,Linux对线程数有限制
    • 线程并发导致第三方服务瘫痪

    八、线程与进程的区别

    • 进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有自己的地址空间;
    • 线程是CPU调度和分配的基本单位,它可与同一进程中其他线程共享进程所拥有的全部资源;
    • 线程是进程的一部分,一个线程只属于一个进程,而一个进程可以有多个线程,但至少有一个线程;
    • 线程之间通信比较简单,例如用Exchange,进程之间通信比较复杂,比如通过信号、套接字、管道、共享内存等;
    • 线程的创建和切换开销比进程小。
    • 了解cgroups概念
    • 线程与进程的区别

    相关文章

      网友评论

          本文标题:如何更好的使用线程

          本文链接:https://www.haomeiwen.com/subject/xjnzsktx.html