`

Java多线程之 concurrent 并发包

阅读更多
  
Java Tutorials -> Concurrency:
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
Java Concurrency Utilities:
http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/index.html


作者 Doug Lea 的个人主页,里头不少好东西:
http://g.oswego.edu/



http://www.vogella.com/articles/JavaConcurrency/article.html
http://tutorials.jenkov.com/java-util-concurrent/index.html

concurrent 包详解:
http://www.cnblogs.com/crazybit/p/3150806.html


线程同步: 待完善。。。
concurrent 包之前,我们可以使用 synchronized 关键字实现线程同步;cooncurrent 包之后,实现 synchronization 的方式除了 synchronized keyword 之外,你还可以使用:
CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CyclicBarrier: A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
Semaphore



如果通过ExecutorService创建了n个线程,那在主线程中是怎么知道ExecutorService中所有的Callable是否都已经执行完毕那?答案是Callable接口的返回值!Callable接口是有返回值的,该返回值封装在ExecutorService的返回值Future里。Future值返回的时候,也就是ExecutorService所起的线程执行完毕的时候;而主线程中,可以将所起线程的返回值Future赋给一个局部变量,从而实现“所起线程未执行完毕时主线程卡在局部变量的赋值操作上,所起线程执行完毕后主线程才继续往下走”的效果。
http://stackoverflow.com/questions/3269445/executorservice-how-to-wait-for-all-tasks-to-finish


使用ExecutorService,一定记得在用完后调用其executorService.shutdown()将其shutdown掉;如果你未调用shutdown()的话,则executorService所起的线程不会退出(这些线程在等着你往其中加入更多的tasks),而这会导致jvm无法退出。
shutdown()方法不会立即terminated掉executorService,只是使其不再接受新的tasks,已submmit入其中的tasks会继续执行,这些already submmitted tasks都执行完后,executorService才会真正的terminated。
如果想立即terminated掉executorService,使用executorService.shutdownNow(),该方法不光使executorService不再接受新的tasks,而且会使其尝试终止所有已提交(尚未开始或尚未完成)的tasks。
http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
引用
Closing an ExecutorService
When you are done using the ExecutorService you should shut it down, so the threads do not keep running.
For instance, if your application is started via a main() method and your main thread exits your application, the application will keep running if you have an active ExexutorService in your application. The active threads inside this ExecutorService prevents the JVM from shutting down.
To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.
If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.




invokeAll 是 blocking 的,future.get 也是 blocking 的。那么,invokeAll 后,在 for 里的 future.get 会阻塞当前线程吗?
invokeAll(tasks),即调用不带超时的 invokeAll 后, future.get 肯定不会阻塞当前线程,因为 invokeAll(tasks) 阻塞结束后,所有的 tasks 的 Future.isDone 都已经是 true 了(Returns 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 true)。
invokeAll(tasks, timeout,unit),即调用带超时的 invokeAll 后,future.get 其实也不会阻塞当前线程,因为这是 tasks 或者是 completed,或者是 cancelled了,详见带超时invokeAll的注释。
代码例子:待补
引申
试想一种场景:实现类似 invokeAll 的批量提交 task,但又不希望其阻塞当前外围线程,怎么做? 待补且查。。。。
http://stackoverflow.com/questions/18493318/is-there-a-non-blocking-method-analogous-to-executorservice-invokeall
http://stackoverflow.com/questions/826212/java-executors-how-to-be-notified-without-blocking-when-a-task-completes



invokeAll vs CompletionService:待补



execute() 和 submit() :
这两个方法都是立即提交 task 给线程池中的线程,不会阻塞当前外围线程的执行。但它们还是有些区别的:
http://stackoverflow.com/questions/3929342/choose-between-executorservices-submit-and-executorservices-execute
主要有一下几点:
1. execute 只可以传 Runnable 作为参数,submit() 的参数既可以 Runnable,也可以是并发包里新增的 Callable。
2. submit 的返回值是包含了 result 的 Future,而 execute 的返回值为 void。
3. 当提交的任务在线程池中执行遇到异常时:
submit 会将抛出的异常绑定到其返回结果 Future 上,当你试图在外围线程中调用 Future.get() 时,会抛出以 Future 绑定的异常作为 cause 的 ExecutionException;
execute 则会导致运行 task 的线程的 UncaughtExceptionHandler 被执行。
引申:
当 使用 execute 提交 task 到 threadpool 中,如果发生异常,会使运行 task 的线程 terminated 掉吗? 待补。。。





关于 RejectedExecutionException:
http://stackoverflow.com/questions/8183205/what-could-cause-of-rejectedexecutionexception
http://examples.javacodegeeks.com/core-java/util/concurrent/rejectedexecutionexception/java-util-concurrent-rejectedexecutionexception-how-to-solve-rejectedexecutionexception/
抛出该异常可能有两种原因:
1. executor 已经 shuttdown 掉;
2. 线程池的 task queue 满了且所有 worker thread 都没闲着,而你恰好此时将往其中提交(使用execute(),或submit())新的task。
当 task 的执行比较耗时,且 task 又比较多致使其迅速将 task queue 占满时,第二种抛 RejectedExecutionException 的情况就极有可能发生。这时,我们就需要某种机制,来保证此种情况下线程池任然能够有条不紊正常的工作:
http://stackoverflow.com/questions/2001086/how-to-make-threadpoolexecutors-submit-method-block-if-it-is-saturated





Using Callable to Return Results From Runnables:
https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6



ReentrantReadWriteLock:
Many readers may acquire the read lock at once, as long as the write lock is free; writer may acquire the write lock only if no other lock is acquired (either read or write).
http://java.dzone.com/news/java-concurrency-read-write-lo?page=0,0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics