#sleep | wait 关于释放锁和线程的区别
- sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,将执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
- wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态
#Thread 的问题
- new Thread的弊端如下:
- 每次new Thread新建对象性能差。
- 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
- 缺乏更多功能,如定时执行、定期执行、线程中断。
- 相比new Thread,Java提供的四种线程池的好处在于:
- 重用存在的线程,减少对象创建、消亡的开销,性能佳。
- 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
- 提供定时执行、定期执行、单线程、并发数控制等功能。
#线程池 ##线程池按以下行为执行任务
- 当线程数小于核心线程数时,创建线程。
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- 当线程数大于等于核心线程数,且任务队列已满
- 若线程数小于最大线程数,创建线程
- 若线程数等于最大线程数,抛出异常,拒绝任务
##Java通过Executors提供四种线程池,分别为:
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个定时线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序( FIFO, LIFO, 优先级)执行
- newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。由于线程池无限大,newCachedThreadPool 大家一般不用就是这样的原因,因为它的最大值是在初始化的时候设置为 Integer.MAX_VALUE,一般来说机器都没那么大内存给它不断使用
###newScheduleThreadPool Demo
public static void testScheduledThreadPool() {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
for (int i = 0; i < 10; i++) {
pool.schedule(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + "is running!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 3, TimeUnit.SECONDS);
}
pool.shutdown();
}
pool-1-thread-1is running!
pool-1-thread-2is running!
pool-1-thread-1is running!
pool-1-thread-2is running!
pool-1-thread-1is running!
pool-1-thread-2is running!
pool-1-thread-1is running!
pool-1-thread-2is running!
pool-1-thread-1is running!
pool-1-thread-2is running!
Executor.submit() Demo
public static void testExecutorSubmitMethod() {
ExecutorService pool = Executors.newFixedThreadPool(2);
Future<String> future[] = new Future[10];
for (int i = 0; i < 10; i++) {
future[i] = pool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(10);
return Thread.currentThread().getName();
}
});
}
for (Future<String> f : future) {
try {
String result = f.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
pool.shutdown();
}
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
#Lock | ReadWriteLock 比较好的模板总结:http://blog.youkuaiyun.com/qq_20641565/article/details/53208909
此外,注意搭配!
- synchronized { wait , notify|notifyAll}
- Lock {condition.await(), condition.signal()|condition.signalAll()}
#CyclicBarrier 适合执行子任务完了再执行主任务的情况 ##Demo
package BarrierPackage;
import java.util.concurrent.CyclicBarrier;
/**
* Created by pinker on 17-2-23.
*/
public class CycliCarrierDemo {
public static void main(String[] args) {
CyclicBarrier pool=new CyclicBarrier(7,new MainTask());
for(int i=0;i<7;i++){
new Thread(new SubTask(pool)).start();
}
}
}
package BarrierPackage;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* Created by pinker on 17-2-24.
*/
public class SubTask implements Runnable {
private CyclicBarrier barrier;
public SubTask(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
Thread.sleep(1000);//模仿子任务执行时间!
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行完毕,已通知主任务!");
try {
barrier.await();//通知障碍器已经完成!
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
Thread-0执行完毕,已通知主任务!
Thread-1执行完毕,已通知主任务!
Thread-2执行完毕,已通知主任务!
Thread-3执行完毕,已通知主任务!
Thread-4执行完毕,已通知主任务!
Thread-5执行完毕,已通知主任务!
Thread-6执行完毕,已通知主任务!
主任务开始执行了!