并发队列:两种: 阻塞队列,非阻塞队列
线程池 -- 阻塞队列
非阻塞队列
public class Test01 {
public static void main(String[] args) {
// 无边界队列:没有长度限制
ConcurrentLinkedQueue<String> clq = new ConcurrentLinkedQueue<>();
// 入队
clq.add("java");
clq.add("MySQL");
clq.add("Spring");
// 出队:
System.out.println(clq.poll()); // java -- 出队,并且在队列中移除元素
System.out.println(clq.size()); // 2
System.out.println("----------------");
System.out.println(clq.peek()); // MySQL -- 输出,但是不在队列中移除元素
System.out.println(clq.size()); // 2
}
}
阻塞队列
public class Test01 {
public static void main(String[] args) throws InterruptedException {
/***
* 查看API得知:
* BlockingQueue是个接口
* ArrayBlockingQueue, DelayQueue, LinkedBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue
*/
LinkedBlockingQueue<String> bq = new LinkedBlockingQueue<>(3);// 长度为3
bq.offer("Java");
bq.offer("C++");
bq.offer("PHP");
System.out.println(bq.poll());
bq.offer("Oracle",3, TimeUnit.SECONDS);
System.out.println(bq.poll());
System.out.println(bq.poll());
System.out.println(bq.poll());
}
}
线程池底层原理--> ThreadPoolExecutor
public class ThreadPool {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 2, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3));
// 利用线程池里的线程开始执行任务:
// 执行第一个任务
pool.execute(new TestThread());
// 执行第2个任务
pool.execute(new TestThread());
pool.execute(new TestThread());
pool.execute(new TestThread());
// 执行第4个任务
pool.execute(new TestThread());
// 核心线程执行一个,队列里有三个,这时再创建一个新的线程
// 线程池有几个线程:2个 : 一个核心线程+ 一个新创建好的线程 == 最大线程数2
// 执行第5个任务
pool.execute(new TestThread()); // 出现异常
// 关闭线程池:
pool.shutdown();
}
}
class TestThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
线程池的分类
可缓存 , 定长 , 定时 , 单例
// 可缓存
public class Test01 {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for (int i =1;i<=100;i++){
es.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
es.shutdown();
}
}
// 定长 --> 核心进程数
public class Test01 {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
for (int i =1;i<=100;i++){
es.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
es.shutdown();
}
}
// 定时
public class Test01 {
public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(3);
for (int i =1;i<=100;i++){
ses.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
},3, TimeUnit.SECONDS);
}
ses.shutdown();
}
}
// 单例
public class Test01 {
public static void main(String[] args) {
ExecutorService es = Executors.newSingleThreadExecutor(); // 这个类中,核心线程和新建线程数都是1
for (int i =1;i<=100;i++){
es.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
es.shutdown();
}
}
Callable原理,多线程执行Callable任务
public class Test01 implements Callable<Integer> {
// 重写call 方法,这个方法:有返回值,有抛出异常
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return new Random().nextInt(10);
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 缺点:创建线程方式比较繁琐:
// 创建线程对象:
Test01 tt = new Test01();
// 启动线程:
FutureTask<Integer> ft = new FutureTask<>(tt);
Thread t = new Thread(ft);
t.start();
// 返回值自己获取
System.out.println(ft.isDone());
Integer i = ft.get();
System.out.println(i);
System.out.println(ft.isDone());
}
}
Callable最重要的底层是FutureTask
这是它的构造器,在这个类中有几个重要的属性
看了上面的图,再看看它的构造器:
在线程执行中调用start()方法本质上是调用FutureTask的run()方法
我们在最终取值的时候利用的是get()方法
用线程池解决上面的Callable例子
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(3);
for (int i = 1;i<=100;i++){
Future<String> f = es.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return Thread.currentThread().getName();
}
});
String s = f.get();
System.out.println(s);
}
es.shutdown();
}
}
这个方法每运行一次线程睡眠2秒,夸张的阻塞效果
优化版
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(3);
ArrayList<Future> list = new ArrayList<>();
for (int i = 1;i<=100;i++){
Future<String> f = es.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return Thread.currentThread().getName();
}
});
list.add(f);
}
for (Future future: list) {
String s = (String) future.get();
System.out.println(s);
}
es.shutdown();
}
}