Java并发编程实践-读后感(1-14.4)

-对于网站客流量统计,可以通过atomic类实现



也可以通过在service前加synchronized 关键字来保证此方法的原子性,但是不推荐这么做,性能太差


-加锁可以保证可见性与原子性,volatile变量只能保证可见性

对此我的理解是:

  可见性:所见即所得,为多个线程操作后的最新值。

  volatile最好用在原子性操作中,例如A=B而不要放在A++中,因为A=A+1为两步操作


-常用的一些同步对象:

--同步容器:Vector->CopyOnWriteArrayList                    list相关的同步容器

                       HashTable->ConcurrentHashMap            map相关的同步容器

                       BlockingQueue                                             FIFO同步队列,支持生产者-消费者设计模式的有界队列

--Synchronizer:

                     CountDownLatch                 countDown方法做递减操作,await方法等待递减到0或者线程中断,感觉多人游戏里的准备后开始可以用这个实现

package five;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class Driver {

	public static void main(String[] args) throws InterruptedException {
		int cnt = 5;
		CountDownLatch startLatch = new CountDownLatch(1);
		CountDownLatch doneLatch = new CountDownLatch(cnt);
		Executor executor = Executors.newCachedThreadPool();
		for (int i = 0; i < 5; i++) {
			executor.execute(new Worker(startLatch, doneLatch));
		}
		System.out.println("ready!!");
		startLatch.countDown();
		System.out.println("done!!");
		doneLatch.await();
	}
}

package five;

import java.util.concurrent.CountDownLatch;

public class Worker implements Runnable {

	private CountDownLatch startLatch;
	private CountDownLatch doneLatch;
	public Worker(CountDownLatch startLatch,CountDownLatch doneLatch) {
		this.startLatch = startLatch;
		this.doneLatch = doneLatch;
	}
	
	@Override
	public void run() {
		try {
			startLatch.await();
			System.out.println("start!!");
			doneLatch.countDown();
		} catch (Exception e) {
			
		}
	}

}


                      FutureTask                          实现了callable接口,Future.get可以取得返回

package five;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class PreLoader {

	class Product {
		private int id;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}
	}
	private FutureTask<Product> task = new FutureTask<>(new Callable<Product>() {
		@Override
		public Product call() throws Exception {
			Product product = new Product();
			product.setId(1);
			return product;
		}
	});
	
	public Product run() throws InterruptedException, ExecutionException {
		Thread thread = new Thread(task);
		thread.start();
		return task.get();
	}
}

                    Semaphore  一个计数信号量,aquire()获得一个许可,release()添加一个许可,如果没有可用许可,那么aquire会被阻塞,直到有可用的为止

粗略实现数据连接池:

package five;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;

public class DataSource {

	class Con{
		private boolean userd;
		private int id;
		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public boolean isUserd() {
			return userd;
		}

		public void setUserd(boolean userd) {
			this.userd = userd;
		}
		public boolean equals(Con con) {
			if (this.getId() == con.getId() && this.userd == con.isUserd()) {
				return true;
			}
			return false;
		}
	}
	
	private Semaphore semaphore;
	private List<Con> cons = new ArrayList<Con>();
	public DataSource(int conNum) {
		semaphore = new Semaphore(conNum);
		for (int i =0; i < conNum; i++) {
			Con con = new Con();
			cons.add(con);
		}
		
	}
	
	public Con getConnection() throws InterruptedException {
		semaphore.acquire();
		return getNextAvaCon();
	} 
	
	public void putConnection(Con con) {
		if (markAsUserd(con)) {
			semaphore.release();
		}
	}
	
	private synchronized Con getNextAvaCon() {
		for (int i = 0; i < cons.size(); i++) {
			Con con = cons.get(i);
			if (!con.isUserd()) {
				con.setUserd(true);
				return con;
			}
		}
		return null;
	}
	
	private synchronized boolean markAsUserd(Con con) {
		for (int i = 0; i < cons.size(); i++) {
			Con conIndex = cons.get(i);
			if (conIndex.equals(con)) {
				if (conIndex.isUserd()) {
					cons.get(i).setUserd(false);
					return true;
				} else {
					return false;
				}
			} 
		}
		return false;
	}
	
}


6.executor框架系列

Executors.newFixedThreadPool 创建一个定长的线程池

Executors.newCachedThreadPool创建一个可缓存的线程池

Executors.newScheduledThreadPool 创建一个定长的线程池,并支持定时以及周期性的任务,jdk1.5后 取代Timer.


ExecutorService 生命周期的三种状态:运行,关闭,终止

shutdown()执行以前提交的任务顺序关闭

shutdownNow()停止所有正在执行的活动任务。


ExecutorCompletionService可以以BlockingQueue<Future>作为参数,返回一些列执行完后的值


线程未捕获异常的处理:

由UncaughtExceptionHandler和ThreadFactory处理,其中线程池中可以传入自定义的ThreadFactory进行处理。


线程池通用的构造函数


public ThreadPoolExecutor (

             int corePoolSize //核心池大小
             int maximumPoolSize, //最大池的大小
             long keepAliveTime, //存活时间
             TimeUnit  timeUnit,  //时间单位
             BlockingQueue<Runnable> workQueue,              //工作线程
             ThreadFactory  factory //线程工程,对线程进行自定义加工
            RejectedExecutionHandler hanlder //饱和策略
) {...}


对于线程池的三个钩子方法,我们可以自定义一些统计信息或者日志信息。我们可以用ThreadLocal在beforeExecute 和afterExecute之间进行传输数据

以下为自定义线程池

package eight;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class TimingThreadPoolExecutor extends ThreadPoolExecutor {

	private ThreadLocal<Long> startTime = new ThreadLocal<Long>();
	private AtomicLong taskNum = new AtomicLong();
	private AtomicLong totalTime = new AtomicLong();
	
	public TimingThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
			long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
		// TODO Auto-generated constructor stub
	}
	
	protected void beforeExecute(Thread t, Runnable r) {
		startTime.set(System.nanoTime());
		super.beforeExecute(t, r);
	}
	
	protected void afterExecute(Runnable r, Throwable t) {
		taskNum.incrementAndGet();
		totalTime.addAndGet(System.nanoTime() - startTime.get());
		super.afterExecute(r, t);
	}
	
	protected void terminated() {
		long avgTime = totalTime.get()/taskNum.get();
		super.terminated();
	}

}

调节共享对象访问机制有 synchronized 、volatile、ReentranLock

死锁恢复:用lock的trylock方法指定超时时间

读写锁:能够被多个读者访问,只能被一个写着访问,两者不能同时进行。ReadWriteLock


ReentranLock与semaphore互相实现的代码:

package footeen;
/**
 * 用lock实现semaphore*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SemaphoreOnLock {

	private final Lock lock = new ReentrantLock();
	private int avalibleNum;
	private final Condition condition = lock.newCondition();
	
	public SemaphoreOnLock(int avalibleNum) {
		lock.lock();
		try {
			this.avalibleNum = avalibleNum;
		} finally {
			lock.unlock();
		}
	}
	
	public void aquire() {
		lock.lock();
		try {
			if (avalibleNum <= 0) condition.await();
			--avalibleNum;
		} catch (Exception e){
			
		} finally {
			lock.unlock();
		}
	}
	
	public void release() {
		lock.lock();
		try {
			++avalibleNum;
			condition.signal();
			
		} finally {
			lock.unlock();
		}
	}
}

package footeen;

import java.util.concurrent.Semaphore;

/**
 * 用信号量实现lock*/
public class LockOnSemaphore {

	private final Semaphore semaphore = new Semaphore(1);
	
	public void lock() {
		try {
			semaphore.acquire();
		} catch (Exception e) {
			
		}
	}
	
	public void unlock() {
		semaphore.release();
	}
}


                      


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值