Android 多線程使用和線程同步與安全

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方法代表執(zhí)行之景,需要傳入一個(gè)Runnable斤富,自動(dòng)執(zhí)行

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;
}

主要三個(gè)方法
void shutdown(); 代表關(guān)閉線程池,不能再讓該線程池添加任務(wù)锻狗。但是在執(zhí)行中的任務(wù)和排隊(duì)中的任務(wù)不會(huì)受到影響满力,全部執(zhí)行完才會(huì)結(jié)束
List<Runnable> shutdownNow(); 代表結(jié)束線程池。會(huì)通過Thread.interrput()來試圖結(jié)束正在執(zhí)行的任務(wù)轻纪,隊(duì)列中的任務(wù)不會(huì)執(zhí)行油额,并且將其返回。也會(huì)等待所有任務(wù)都結(jié)束才會(huì)真正結(jié)束刻帚。
<T> Future<T> submit(Callable<T> task); 代表執(zhí)行一個(gè)帶阻塞式的任務(wù)潦嘶,可以使用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 代表默認(rèn)線程個(gè)數(shù)崇众。當(dāng)線程池被創(chuàng)建掂僵,就默認(rèn)創(chuàng)建多少個(gè);當(dāng)線程池在一個(gè)一個(gè)回收顷歌,回收都默認(rèn)個(gè)數(shù)后就不會(huì)回收了
maximumPoolSize 代表最大線程格數(shù)锰蓬。當(dāng)線程池中線程超過最大數(shù),就會(huì)進(jìn)入排隊(duì)隊(duì)列中眯漩。
keepAliveTime & unit 兩個(gè)一起使用芹扭,代表線程等待被回收的時(shí)間。當(dāng)線程執(zhí)行完赦抖,具體多少后會(huì)被回收舱卡,取決與這個(gè)時(shí)間
workQueue 代表任務(wù)隊(duì)列。當(dāng)線程池中線程超過最大數(shù)队萤,再添加任務(wù)先添加到此隊(duì)列轮锥,等待線程被回收后,線程池當(dāng)前線程數(shù)小于最大數(shù)要尔,將會(huì)取出執(zhí)行交胚。

ThreadPoolExecutor 常用實(shí)現(xiàn)

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

代表一個(gè)可以添加無數(shù)個(gè)任務(wù),默認(rèn)線程數(shù)0盈电,1分鐘會(huì)被回收的線程池蝴簇。

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>());
}

代表固定線程數(shù)的線程池,并且不會(huì)被回收匆帚,不能擴(kuò)展熬词。一般用來處理集中瞬時(shí)爆發(fā)的任務(wù),之后需要調(diào)用shutdown()來結(jié)束且回收

線程同步與安全

本質(zhì)就是資源問題

volatile

當(dāng)子線程使用了主線程的內(nèi)對象,其實(shí)子線程會(huì)把主線程的內(nèi)對象拷貝到自己的內(nèi)存塊互拾,當(dāng)子線程這個(gè)對象的值發(fā)送改變后歪今,主線程中這個(gè)對象不會(huì)發(fā)送變化,JVM這樣做是為了效率問題颜矿。為主線程的內(nèi)對象加上volatile關(guān)鍵字寄猩,會(huì)讓此對象具有同步性,這個(gè)時(shí)候在子線程修改對象值的時(shí)候骑疆,會(huì)同步到主線程內(nèi)對象上田篇,相反主線程修改也會(huì)同步到子線程。

ATomic

使用了volatile后箍铭,對象會(huì)有同步性泊柬,但是當(dāng)修改這個(gè)值是需要分幾步執(zhí)行時(shí)≌┗穑可能在修改過程中切換到另一個(gè)線程從頭開始修改兽赁,導(dǎo)致了程序的數(shù)據(jù)錯(cuò)亂。所以可以在Atomic來作為對象冷守,比如++ --刀崖,讓修改操作不僅僅具有同步性,而且具有原子性拍摇。

synchronized

同步的意思亮钦,保護(hù)代碼塊在多線程同時(shí)調(diào)用的時(shí)候,具有原子性授翻,不會(huì)出現(xiàn)數(shù)據(jù)錯(cuò)誤或悲。

monitor(鎖)

使用synchronized需要用到孙咪,可以理解為鎖堪唐。
當(dāng)為代碼塊使用synchronized (this) {}, 會(huì)使用當(dāng)前類對象的鎖。
當(dāng)其他線程同時(shí)調(diào)用時(shí)翎蹈,這個(gè)鎖還處于未解鎖淮菠,其他線程會(huì)在后面等待被執(zhí)行,直至鎖被解鎖荤堪,再執(zhí)行后面的線程任務(wù)合陵。
當(dāng)為代碼塊使用synchronized (${other monitor}) {},當(dāng)其他線程同時(shí)調(diào)用時(shí)澄阳,執(zhí)行的方法中有這個(gè)鎖才會(huì)等待執(zhí)行拥知,否則不受鎖限制。

死鎖

當(dāng)A方法碎赢,代碼塊用了A鎖低剔,A鎖中使用了B鎖;
當(dāng)B方法,代碼塊用了B鎖襟齿,B鎖中使用了A鎖姻锁;
A線程調(diào)用A方法,B線程調(diào)用B方法猜欺,且同時(shí)調(diào)用位隶。A執(zhí)行后A鎖會(huì)鎖住,B執(zhí)行后B鎖會(huì)鎖住开皿。A鎖中執(zhí)行到B鎖的時(shí)候涧黄,發(fā)現(xiàn)B鎖鎖住了,就會(huì)等待解鎖副瀑;B鎖中執(zhí)行到A鎖的時(shí)候弓熏,發(fā)現(xiàn)A鎖鎖住了,也會(huì)等待解鎖糠睡。這樣就成死鎖了挽鞠。

樂觀鎖悲觀鎖

這是操作數(shù)據(jù)庫才能的遇到的問題,一般在Android中不會(huì)出現(xiàn)
樂觀鎖的意思就是不加鎖狈孔,從數(shù)據(jù)庫拿了數(shù)據(jù)做業(yè)務(wù)邏輯修改數(shù)據(jù)信认,存入數(shù)據(jù)庫的時(shí)候,再拿數(shù)據(jù)庫最新數(shù)據(jù)和當(dāng)時(shí)拿出來的數(shù)據(jù)對比均抽,值沒有被其他人修改就提價(jià)修改嫁赏;值有差別,則再取出值重新做業(yè)務(wù)邏輯油挥。
悲觀鎖的意思就是我從數(shù)據(jù)庫開始讀取數(shù)據(jù)的時(shí)候潦蝇,我就加鎖,不允許其他人修改數(shù)據(jù)深寥。我拿到數(shù)據(jù)處理完直接更新數(shù)據(jù)庫攘乒,之后我再解鎖,讓別人操作惋鹅。

靜態(tài)鎖

一般用于單例模式
getInstance() 可能存在多線程同時(shí)調(diào)用则酝,防止多次初始化并且覆蓋操作,需要加上靜態(tài)鎖
synchronized(Class.class)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末闰集,一起剝皮案震驚了整個(gè)濱河市沽讹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌武鲁,老刑警劉巖爽雄,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沐鼠,居然都是意外死亡挚瘟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刽沾,“玉大人本慕,你說我怎么就攤上這事〔嗬欤” “怎么了锅尘?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長布蔗。 經(jīng)常有香客問我藤违,道長,這世上最難降的妖魔是什么纵揍? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任顿乒,我火速辦了婚禮,結(jié)果婚禮上泽谨,老公的妹妹穿的比我還像新娘璧榄。我一直安慰自己,他們只是感情好吧雹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布骨杂。 她就那樣靜靜地躺著,像睡著了一般雄卷。 火紅的嫁衣襯著肌膚如雪搓蚪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死雳灾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拂盯。 我是一名探鬼主播佑女,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼记靡,長吁一口氣:“原來是場噩夢啊……” “哼谈竿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起摸吠,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤空凸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后寸痢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呀洲,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了道逗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兵罢。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖滓窍,靈堂內(nèi)的尸體忽然破棺而出卖词,到底是詐尸還是另有隱情,我是刑警寧澤吏夯,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布此蜈,位于F島的核電站,受9級特大地震影響噪生,放射性物質(zhì)發(fā)生泄漏裆赵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一跺嗽、第九天 我趴在偏房一處隱蔽的房頂上張望战授。 院中可真熱鬧,春花似錦桨嫁、人聲如沸陈醒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钉跷。三九已至,卻和暖如春肚逸,著一層夾襖步出監(jiān)牢的瞬間爷辙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工朦促, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膝晾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓务冕,卻偏偏與公主長得像血当,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子禀忆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355