美文网首页
Android 多线程使用和线程同步与安全

Android 多线程使用和线程同步与安全

作者: 一迅 | 来源:发表于2021-06-21 11:07 被阅读0次

    executor 线程池

    public interface Executor {
        /**
         * Executes the given command at some time in the future.  The command
         * may execute in a new thread, in a pooled thread, or in the calling
         * thread, at the discretion of the {@code Executor} implementation.
         *
         * @param command the runnable task
         * @throws RejectedExecutionException if this task cannot be
         * accepted for execution
         * @throws NullPointerException if command is null
         */
        void execute(Runnable command);
    }
    

    execute方法代表执行,需要传入一个Runnable,自动执行

    public interface ExecutorService extends Executor {
    
        /**
         * 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.
         */
        void shutdown();
    
        /**
         * Attempts to stop all actively executing tasks, halts the
         * processing of waiting tasks, and returns a list of the tasks
         * that were awaiting execution.
         *
         * <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.  For example, typical
         * implementations will cancel via {@link Thread#interrupt}, so any
         * task that fails to respond to interrupts may never terminate.
         *
         * @return list of tasks that never commenced execution
         */
        List<Runnable> shutdownNow();
    
        /**
         * Returns {@code true} if this executor has been shut down.
         *
         * @return {@code true} if this executor has been shut down
         */
        boolean isShutdown();
    
        /**
         * Returns {@code true} if all tasks have completed following shut down.
         * Note that {@code isTerminated} is never {@code true} unless
         * either {@code shutdown} or {@code shutdownNow} was called first.
         *
         * @return {@code true} if all tasks have completed following shut down
         */
        boolean isTerminated();
    
        /**
         * Blocks until all tasks have completed execution after a shutdown
         * request, or the timeout occurs, or the current thread is
         * interrupted, whichever happens first.
         *
         * @param timeout the maximum time to wait
         * @param unit the time unit of the timeout argument
         * @return {@code true} if this executor terminated and
         *         {@code false} if the timeout elapsed before termination
         * @throws InterruptedException if interrupted while waiting
         */
        boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException;
    
        /**
         * Submits a value-returning task for execution and returns a
         * Future representing the pending results of the task. The
         * Future's {@code get} method will return the task's result upon
         * successful completion.
         *
         * <p>
         * If you would like to immediately block waiting
         * for a task, you can use constructions of the form
         * {@code result = exec.submit(aCallable).get();}
         *
         * <p>Note: The {@link Executors} class includes a set of methods
         * that can convert some other common closure-like objects,
         * for example, {@link java.security.PrivilegedAction} to
         * {@link Callable} form so they can be submitted.
         *
         * @param task the task to submit
         * @param <T> the type of the task's result
         * @return a Future representing pending completion of the task
         * @throws RejectedExecutionException if the task cannot be
         *         scheduled for execution
         * @throws NullPointerException if the task is null
         */
        <T> Future<T> submit(Callable<T> task);
    
        /**
         * Submits a Runnable task for execution and returns a Future
         * representing that task. The Future's {@code get} method will
         * return the given result upon successful completion.
         *
         * @param task the task to submit
         * @param result the result to return
         * @param <T> the type of the result
         * @return a Future representing pending completion of the task
         * @throws RejectedExecutionException if the task cannot be
         *         scheduled for execution
         * @throws NullPointerException if the task is null
         */
        <T> Future<T> submit(Runnable task, T result);
    
        /**
         * Submits a Runnable task for execution and returns a Future
         * representing that task. The Future's {@code get} method will
         * return {@code null} upon <em>successful</em> completion.
         *
         * @param task the task to submit
         * @return a Future representing pending completion of the task
         * @throws RejectedExecutionException if the task cannot be
         *         scheduled for execution
         * @throws NullPointerException if the task is null
         */
        Future<?> submit(Runnable task);
    
        /**
         * Executes the given tasks, returning a list of Futures holding
         * their status and results when all complete.
         * {@link Future#isDone} is {@code true} for each
         * element of the returned list.
         * Note that a <em>completed</em> task could have
         * terminated either normally or by throwing an exception.
         * The results of this method are undefined if the given
         * collection is modified while this operation is in progress.
         *
         * @param tasks the collection of tasks
         * @param <T> the type of the values returned from the tasks
         * @return a list of Futures representing the tasks, in the same
         *         sequential order as produced by the iterator for the
         *         given task list, each of which has completed
         * @throws InterruptedException if interrupted while waiting, in
         *         which case unfinished tasks are cancelled
         * @throws NullPointerException if tasks or any of its elements are {@code null}
         * @throws RejectedExecutionException if any task cannot be
         *         scheduled for execution
         */
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException;
    
        /**
         * Executes the given tasks, returning a list of Futures holding
         * their status and results
         * when all complete or the timeout expires, whichever happens first.
         * {@link Future#isDone} is {@code true} for each
         * element of the returned list.
         * Upon return, tasks that have not completed are cancelled.
         * Note that a <em>completed</em> task could have
         * terminated either normally or by throwing an exception.
         * The results of this method are undefined if the given
         * collection is modified while this operation is in progress.
         *
         * @param tasks the collection of tasks
         * @param timeout the maximum time to wait
         * @param unit the time unit of the timeout argument
         * @param <T> the type of the values returned from the tasks
         * @return a list of Futures representing the tasks, in the same
         *         sequential order as produced by the iterator for the
         *         given task list. If the operation did not time out,
         *         each task will have completed. If it did time out, some
         *         of these tasks will not have completed.
         * @throws InterruptedException if interrupted while waiting, in
         *         which case unfinished tasks are cancelled
         * @throws NullPointerException if tasks, any of its elements, or
         *         unit are {@code null}
         * @throws RejectedExecutionException if any task cannot be scheduled
         *         for execution
         */
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                      long timeout, TimeUnit unit)
            throws InterruptedException;
    
        /**
         * Executes the given tasks, returning the result
         * of one that has completed successfully (i.e., without throwing
         * an exception), if any do. Upon normal or exceptional return,
         * tasks that have not completed are cancelled.
         * The results of this method are undefined if the given
         * collection is modified while this operation is in progress.
         *
         * @param tasks the collection of tasks
         * @param <T> the type of the values returned from the tasks
         * @return the result returned by one of the tasks
         * @throws InterruptedException if interrupted while waiting
         * @throws NullPointerException if tasks or any element task
         *         subject to execution is {@code null}
         * @throws IllegalArgumentException if tasks is empty
         * @throws ExecutionException if no task successfully completes
         * @throws RejectedExecutionException if tasks cannot be scheduled
         *         for execution
         */
        <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException;
    
        /**
         * Executes the given tasks, returning the result
         * of one that has completed successfully (i.e., without throwing
         * an exception), if any do before the given timeout elapses.
         * Upon normal or exceptional return, tasks that have not
         * completed are cancelled.
         * The results of this method are undefined if the given
         * collection is modified while this operation is in progress.
         *
         * @param tasks the collection of tasks
         * @param timeout the maximum time to wait
         * @param unit the time unit of the timeout argument
         * @param <T> the type of the values returned from the tasks
         * @return the result returned by one of the tasks
         * @throws InterruptedException if interrupted while waiting
         * @throws NullPointerException if tasks, or unit, or any element
         *         task subject to execution is {@code null}
         * @throws TimeoutException if the given timeout elapses before
         *         any task successfully completes
         * @throws ExecutionException if no task successfully completes
         * @throws RejectedExecutionException if tasks cannot be scheduled
         *         for execution
         */
        <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                        long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    
    

    主要三个方法
    void shutdown(); 代表关闭线程池,不能再让该线程池添加任务。但是在执行中的任务和排队中的任务不会受到影响,全部执行完才会结束
    List<Runnable> shutdownNow(); 代表结束线程池。会通过Thread.interrput()来试图结束正在执行的任务,队列中的任务不会执行,并且将其返回。也会等待所有任务都结束才会真正结束。
    <T> Future<T> submit(Callable<T> task); 代表执行一个带阻塞式的任务,可以使用Callable,拿到线程的返回值

    ThreadPoolExecutor

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    

    corePoolSize 代表默认线程个数。当线程池被创建,就默认创建多少个;当线程池在一个一个回收,回收都默认个数后就不会回收了
    maximumPoolSize 代表最大线程格数。当线程池中线程超过最大数,就会进入排队队列中。
    keepAliveTime & unit 两个一起使用,代表线程等待被回收的时间。当线程执行完,具体多少后会被回收,取决与这个时间
    workQueue 代表任务队列。当线程池中线程超过最大数,再添加任务先添加到此队列,等待线程被回收后,线程池当前线程数小于最大数,将会取出执行。

    ThreadPoolExecutor 常用实现

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    

    代表一个可以添加无数个任务,默认线程数0,1分钟会被回收的线程池。

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    

    代表单线程的线程池

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    

    代表固定线程数的线程池,并且不会被回收,不能扩展。一般用来处理集中瞬时爆发的任务,之后需要调用shutdown()来结束且回收

    线程同步与安全

    本质就是资源问题

    volatile

    当子线程使用了主线程的内对象,其实子线程会把主线程的内对象拷贝到自己的内存块,当子线程这个对象的值发送改变后,主线程中这个对象不会发送变化,JVM这样做是为了效率问题。为主线程的内对象加上volatile关键字,会让此对象具有同步性,这个时候在子线程修改对象值的时候,会同步到主线程内对象上,相反主线程修改也会同步到子线程。

    ATomic

    使用了volatile后,对象会有同步性,但是当修改这个值是需要分几步执行时。可能在修改过程中切换到另一个线程从头开始修改,导致了程序的数据错乱。所以可以在Atomic来作为对象,比如++ --,让修改操作不仅仅具有同步性,而且具有原子性。

    synchronized

    同步的意思,保护代码块在多线程同时调用的时候,具有原子性,不会出现数据错误。

    monitor(锁)

    使用synchronized需要用到,可以理解为锁。
    当为代码块使用synchronized (this) {}, 会使用当前类对象的锁。
    当其他线程同时调用时,这个锁还处于未解锁,其他线程会在后面等待被执行,直至锁被解锁,再执行后面的线程任务。
    当为代码块使用synchronized (${other monitor}) {},当其他线程同时调用时,执行的方法中有这个锁才会等待执行,否则不受锁限制。

    死锁

    当A方法,代码块用了A锁,A锁中使用了B锁;
    当B方法,代码块用了B锁,B锁中使用了A锁;
    A线程调用A方法,B线程调用B方法,且同时调用。A执行后A锁会锁住,B执行后B锁会锁住。A锁中执行到B锁的时候,发现B锁锁住了,就会等待解锁;B锁中执行到A锁的时候,发现A锁锁住了,也会等待解锁。这样就成死锁了。

    乐观锁悲观锁

    这是操作数据库才能的遇到的问题,一般在Android中不会出现
    乐观锁的意思就是不加锁,从数据库拿了数据做业务逻辑修改数据,存入数据库的时候,再拿数据库最新数据和当时拿出来的数据对比,值没有被其他人修改就提价修改;值有差别,则再取出值重新做业务逻辑。
    悲观锁的意思就是我从数据库开始读取数据的时候,我就加锁,不允许其他人修改数据。我拿到数据处理完直接更新数据库,之后我再解锁,让别人操作。

    静态锁

    一般用于单例模式
    getInstance() 可能存在多线程同时调用,防止多次初始化并且覆盖操作,需要加上静态锁
    synchronized(Class.class)

    相关文章

      网友评论

          本文标题:Android 多线程使用和线程同步与安全

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