一 生產者與消費者模式
public class ThreadTest {
//產品
static class ProductObject {
//線程操作變量可見
public volatile static String value;
}
//生產者線程
static class Producer extends Thread {
Object lock;
public Producer(Object lock) {
this.lock = lock;
}
@Override
public void run() {
//不斷生產產品
while (true) {
synchronized (lock) {//互斥鎖
//產品還沒有被消費,等待
if (ProductObject.value != null) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//產品已經消費完成,生產新的產品
ProductObject.value = "NO:" + System.currentTimeMillis();
System.out.print("生產產品:" + ProductObject.value);
lock.notify();
}
}
}
}
//消費者線程
static class Consumer extends Thread {
Object lock;
public Consumer(Object lock){
this.lock = lock;
}
@Override
public void run() {
while (true){
synchronized (lock){
//沒有產品可以消費
if(ProductObject.value == null){
//等待,阻塞
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print("消費產品:"+ProductObject.value);
ProductObject.value = null;
lock.notify();//消費完成,通知生產者繼續生產
}
}
}
}
public static void main(String[] args){
Object lock = new Object();
new Producer(lock).start();
new Consumer(lock).start();
}
}
二 FutureTask 的便利性
異步任務執行的結果,主線程無法輕易的獲取
1.獲取異步任務的返回值
2.監聽異步任務的執行完畢
3.取消異步任務
public static void main(String[] args) {
Task work = new Task();
FutureTask<Integer> future = new FutureTask<Integer>(work){
@Override
protected void done() {
try {
System.out.println("done:"+get());
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//線程池(使用了預定義的配置)
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(future);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//取消異步任務
future.cancel(true);
try {
//阻塞,等待異步任務執行完畢
System.out.println(future.get()); //獲取異步任務的返回值
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
//異步任務
static class Task implements Callable<Integer>{
//返回異步任務的執行結果
@Override
public Integer call() {
int i = 0;
for(;i < 10;i++){
System.out.println(Thread.currentThread().getName()+"_"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return i;
}
}
}
三 AsyncTask的侷限性
doBackground(call)
call的返回值在Future的done方法中獲取
->onPostExecute
new MyTask().execute();
實例化:
new AsyncTask() -> new FutureTask()
執行:
Executor.execute(mFuture) -> SerialExecutor.myTasks(隊列)
-> (線程池)THREAD_POOL_EXECUTOR.execute
線程池中的所有線程,爲了執行異步任務
CORE_POOL_SIZE 核心線程數
MAXIMUM_POOL_SIZE 最大線程數量
KEEP_ALIVE 1s閒置回收
TimeUnit.SECONDS 時間單位
sPoolWorkQueue 異步任務隊列
sThreadFactory 線程工廠
如果當前線程池中的數量小於corePoolSize,創建並添加的任務。
如果當前線程池中的數量等於corePoolSize,緩衝隊列 workQueue未滿,那麼任務被放入緩衝隊列、等待任務調度執行。
如果當前線程池中的數量大於corePoolSize,緩衝隊列workQueue已滿,並且線程池中的數量小於maximumPoolSize,新提交任務會創建新線程執行任務。
如果當前線程池中的數量大於corePoolSize,緩衝隊列workQueue已滿,並且線程池中的數量等於maximumPoolSize,新提交任務由Handler處理。
當線程池中的線程大於corePoolSize時,多餘線程空閒時間超過keepAliveTime時,會關閉這部分線程。
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
1.線程池容量不夠拋出異常
2.內存泄露
3.一個線程,一個異步任務(?)
public static void main(String[] args) {
int CPU_COUNT = Runtime.getRuntime().availableProcessors();
int CORE_POOL_SIZE = CPU_COUNT + 1;//5
int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; //9
int KEEP_ALIVE = 1;
//任務隊列(128)
final BlockingDeque<Runnable> sPoolWorkQueue = new LinkedBlockingDeque<>(128);
//線程工廠
ThreadFactory sThreaFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@Override
public Thread newThread(@NonNull Runnable r) {
String name = "Thread #" + mCount.getAndIncrement();
System.out.println(name);
return new Thread(r, name);
}
};
//線程池
Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreaFactory);
//執行異步任務
//如果當前線程池中的數量大於corePoolSize,緩衝隊列workQueue已滿,
//並且線程池中的數量等於maximumPoolSize,新提交任務由Handler處理。
//RejectedExecutionException
for (int i = 0; i < 200; i++) {
//相當於new AsyncTask().execute();
THREAD_POOL_EXECUTOR.execute(new MyTask());
}
}
static class MyTask implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
/*while(true){
try {
System.out.println(Thread.currentThread().getName());
//Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}*/
}
}