理解多线程通信
工人A往水桶中倒水、工人B从水桶中取水,只有互相交流才能使得水桶中的水不至于溢出或无水,把两个工人比作线程,线程A往集合中添加元素,线程B往集合中取出元素,就需要通过多线程通信进行协调而有序进行
等待/唤醒机制
- wait(): 让线程处于冻结状态(停止取水)。线程中对象获得线程锁后可执行该方法
- 内置锁:java对象都可以用做实现同步的锁,这些锁为内置锁。
线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
synchronized (obj) {
while (<condition)
obj.wait();// 停止取水
}
// 通过lock()接口获取隐式锁
provite void synchroized method(){
...
Lock l = ...;
l.lock();// 阻止取水
}
- notify():唤醒线程池中一个线程(任意)。如果对象调用了notify方法就会通知某个(正在等待这个对象的控制权的)线程可以继续运行。
- notifyAll():唤醒线程池中的所有线程。如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
{
obj = value; // 加水
obj.notify();// 请继续取水
}
-
lock():获取锁。
unlock():释放锁。 -
Condition接口:替代了Object中的wait notify notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。
可以任意锁进行组合。
await();
signal();
signalAll();
线程池
public static ThreadPoolExecutor mAppThreadPool; // 应用线程池
/**
* 初始化线程池
*/
private void initThreadPool() {
// 根据CPU的核心数获取最佳核心线程数
int corePoolSize = Runtime.getRuntime().availableProcessors() * 4 + 1;
// 线程池的最大线程数
int maxPoolSize = corePoolSize * 4;
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
// 拒绝策列
ThreadPoolExecutor.CallerRunsPolicy handler = new ThreadPoolExecutor.CallerRunsPolicy();
mAppThreadPool = new ThreadPoolExecutor(corePoolSize, maxPoolSize,
10, TimeUnit.SECONDS, workQueue,
Executors.defaultThreadFactory(), handler);
// 允许核心线程池超时回收
mAppThreadPool.allowCoreThreadTimeOut(true);
}
/**
* 获取全局线程池
* @return
*/
public static ExecutorService getThreadPool(){
return mAppThreadPool;
}
AyncTask实现异步任务线程池
AsyncTask mTask = new AsyncTask();
mTask .executeOnExecutor(AppUtils.getThreadPool(),task);
executeOnExecutor(Executor exec, Object… params),该方法接受2个参数,第一个是Executor,第二个是任务参数。Executor主要由四
种类型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
executeOnExecutor是多线程的,即使传入Executor规定为单线程
asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);
asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);
asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);和
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);一样是多线程并发执行的,程
序在每次调用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)时会获取一个新的Executor对
象,这个对象内的线程只执行对应的task,所以无论哪种情况每个task都有一个新的线程来执行,即并发执行。