该系列文章是博主学习笔记,禁止转载,读书交流群:946541246
文章目录
Java并发编程实战五章学习
同步容器类的问题
public class UnsafeVectorHelpers {
public static Object getLast(Vector list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
public static void deleteLast(Vector list) {
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
}
上面代码存在的问题:如果线程A在包含10个元素的Vector上调用getLast,同时线程B在同一个Vector上调用deleteLast,就会出现ArrayIndexOutOfBoundsException
异常
修复:使用客户端加锁,保证是一个原子操作
public class SafeVectorHelpers {
public static Object getLast(Vector list) {
synchronized (list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
}
public static void deleteLast(Vector list) {
synchronized (list) {
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
}
}
同理下面程序也会出现问题
如果有其他线程并发地修改Vector时,则可能导致麻烦。
如果在对Vector进行迭代时,另一个线程删除了一个元素,并且这两个操作交替执行,那么这种迭代方式将抛出ArrayIndexOutOfBoundsException
异常
Vector vector = null;
for (int i = 0; i < vector.size(); i++) {
doSomething(vector.get(i));
}
解决:
Vector vector = null;
synchronized (vector) {
for (int i = 0; i < vector.size(); i++) {
doSomething(vector.get(i));
}
}
迭代器与ConcurrentModificationException
在for-each循环语法,对容器类进行迭代的标准方式都是使用Iterator。如果有其他线程并发地修改容器,会抛出ConcurrentModificationException异常。
List<Object> objects = Collections.synchronizedList(new ArrayList<Object>());
// ...
// 可能抛出ConcurrentModificationException
for (Object o : objects) {
// doSomething
}
要想避免出现ConcurrentModificationException,就必须在迭代过程中持有容器的锁
如果容器的规模很大,或者在每个元素上执行操作的时间很长,那么这些线程将长时间等待
如果不希望在迭代期间对容器加锁,那么一种替代方法就是“克隆”容器,在副本上进行迭代
toString、hashCode和equal等方法也会间接地执行迭代操作,当容器作为另一个容器的元素或键值时,就会出现这种情况。同样,containsAll、removeAll和retainAll等方法,以及把容器作为参数的构造函数,都会对容器进行迭代。所有这些间接的迭代操作都可能抛出ConcurrentModificationException
阻塞方法与中断方法
当代码调用了一个将抛出InterruptedException异常的方法时,你自己的方法也就变成了一个阻塞方法,必须要处理对中断的响应
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class TaskRunnable implements Runnable {
BlockingQueue<Task> queue = new LinkedBlockingQueue<>();
public void run() {
try {
queue.put(new Task() {
});
} catch (InterruptedException e) {
e.printStackTrace();
}
// 当代码调用了一个将抛出InterruptedException异常的
// 方法时,你自己的方法也就变成了一个阻塞方法,
// 但这个方法并没有阻塞住,
// 但isInterrupted还是为false,还是在调用下interrupt,
// 让它变成true吧
while (!Thread.currentThread().isInterrupted()) {
try {
processTask(queue);
} catch (InterruptedException e) {
System.out.println("TaskRunnable.run " + Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
System.out.println("TaskRunnable.run " + Thread.currentThread().isInterrupted());
}
}
}
void processTask(BlockingQueue task) throws InterruptedException {
System.out.println("TaskRunnable.processTask + " + task.take());
throw new InterruptedException();
}
interface Task {
}
public static void main(String[] args) {
TaskRunnable taskRunnable = new TaskRunnable();
new Thread(taskRunnable).start();
}
}
Java并发编程实战六章学习
Executor框架
作用
将请求处理任务的提交与任务的实际执行解耦开来,并且只需采用另一种不同的Executor实现。
package unit6;
import java.util.concurrent.Executor;
/**
* @program: JavaConcurrency
* @description:
* @create: 2020-01-04 14:44
**/
public class ExecutorTest {
public static void main(String[] args) {
RunnableTest runnableTest = new RunnableTest();
AsynchronousExecutor asynchronousExecutor = new AsynchronousExecutor();
SynchronizationExecutor synchronizationExecutor = new SynchronizationExecutor();
asynchronousExecutor.execute(runnableTest);
synchronizationExecutor.execute(runnableTest);
}
/**
* 异步
*/
static class AsynchronousExecutor implements Executor {
@Override
public void execute(Runnable command) {
new Thread(command).start();
}
}
/**
* 同步
*/
static class SynchronizationExecutor implements Executor {
@Override
public void execute(Runnable command) {
command.run();
}
}
static class RunnableTest implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
}
Executor生命周期
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
ExecutorService 生命周期:运行、关闭、以终止
shutdown:执行平缓的关闭过程。不再接受新的任务,同时等待已经提交的任务执行完成——包括那些还未开始执行的任务
shutdownNow:取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务
但shutdownNow无法通过常规方法找出哪些任务已经开始但尚未结束。无法在关闭过程中知道正在执行的任务的状态
public class LifecycleWebServer {
private final ExecutorService exec = Executors.newCachedThreadPool();
public void start() throws IOException {
ServerSocket socket = new ServerSocket(80);
while (!exec.isShutdown()) {
try {
final Socket conn = socket.accept();
exec.execute(new Runnable() {
public void run() {
handleRequest(conn);
}
});
} catch (RejectedExecutionException e) {
if (!exec.isShutdown())
log("task submission rejected", e);
}
}
}
}
使用ExecutorCompletionService提交一组任务
public abstract class Renderer {
private final ExecutorService executor;
Renderer(ExecutorService executor) {
this.executor = executor;
}
void renderPage(CharSequence source) {
final List<ImageInfo> info = scanForImageInfo(source);
CompletionService<ImageData> completionService =
new ExecutorCompletionService<ImageData>(executor);
for (final ImageInfo imageInfo : info)
completionService.submit(new Callable<ImageData>() {
public ImageData call() {
return imageInfo.downloadImage();
}
});
renderText(source);
try {
for (int t = 0, n = info.size(); t < n; t++) {
Future<ImageData> f = completionService.take();
ImageData imageData = f.get();
renderImage(imageData);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
interface ImageData {
}
interface ImageInfo {
ImageData downloadImage();
}
abstract void renderText(CharSequence s);
abstract List<ImageInfo> scanForImageInfo(CharSequence s);
abstract void renderImage(ImageData i);
}
为任务设置定时
public class RenderWithTimeBudget {
private static final Ad DEFAULT_AD = new Ad();
private static final long TIME_BUDGET = 1000;
private static final ExecutorService exec = Executors.newCachedThreadPool();
Page renderPageWithAd() throws InterruptedException {
long endNanos = System.nanoTime() + TIME_BUDGET;
Future<Ad> f = exec.submit(new FetchAdTask());
// Render the page while waiting for the ad
Page page = renderPageBody();
Ad ad;
try {
// Only wait for the remaining time budget
long timeLeft = endNanos - System.nanoTime();
ad = f.get(timeLeft, NANOSECONDS);
} catch (ExecutionException e) {
ad = DEFAULT_AD;
} catch (TimeoutException e) {
ad = DEFAULT_AD;
f.cancel(true);
}
page.setAd(ad);
return page;
}
Page renderPageBody() { return new Page(); }
static class Ad {
}
static class Page {
public void setAd(Ad ad) { }
}
static class FetchAdTask implements Callable<Ad> {
public Ad call() {
return new Ad();
}
}
}
使用invokeAll提交一组限时任务
public class TimeBudget {
private static ExecutorService exec = Executors.newCachedThreadPool();
public List<TravelQuote> getRankedTravelQuotes(TravelInfo travelInfo, Set<TravelCompany> companies,
Comparator<TravelQuote> ranking, long time, TimeUnit unit)
throws InterruptedException {
List<QuoteTask> tasks = new ArrayList<QuoteTask>();
for (TravelCompany company : companies)
tasks.add(new QuoteTask(company, travelInfo));
List<Future<TravelQuote>> futures = exec.invokeAll(tasks, time, unit);
List<TravelQuote> quotes =
new ArrayList<TravelQuote>(tasks.size());
Iterator<QuoteTask> taskIter = tasks.iterator();
for (Future<TravelQuote> f : futures) {
QuoteTask task = taskIter.next();
try {
quotes.add(f.get());
} catch (ExecutionException e) {
quotes.add(task.getFailureQuote(e.getCause()));
} catch (CancellationException e) {
quotes.add(task.getTimeoutQuote(e));
}
}
Collections.sort(quotes, ranking);
return quotes;
}
}
class QuoteTask implements Callable<TravelQuote> {
private final TravelCompany company;
private final TravelInfo travelInfo;
public QuoteTask(TravelCompany company, TravelInfo travelInfo) {
this.company = company;
this.travelInfo = travelInfo;
}
TravelQuote getFailureQuote(Throwable t) {
return null;
}
TravelQuote getTimeoutQuote(CancellationException e) {
return null;
}
public TravelQuote call() throws Exception {
return company.solicitQuote(travelInfo);
}
}
interface TravelCompany {
TravelQuote solicitQuote(TravelInfo travelInfo) throws Exception;
}
interface TravelQuote {
}
interface TravelInfo {
}