日常笔记

字符串

String 内容不可变字符串,底层用了不可变数组 final char []实现,声明不可变好处,如果声明多个相同的字符串,只会创建一个字符串对象,先会去字符串常量池中找,如果有,把对象的引用指向旧对象,旧对象丢弃
StringBuffer(线程安全), StringBuild(线程不安全,效率高) 可变字符串, char []

类初始化顺序

静态变量/静态初始化块 -》变量/初始化块 -》构造函数
继承情况下:
父类静态变量/父类静态初始化块 -》子类静态变量/子类静态初始化块 -》父类变量/父类初始化块 -》 父类构造器 -》 子类变量/子类初始化块 -》 子类构造器
静态变量和静态初始化块按照顺序加载(非静态一样)

集合

集合分为存储值(collection),和key-value(map)
值:List Set
List 有序 可重复
ArrayList 底层数组实现 ,具有索引,查询特定元素快,插入和删除慢(数组在内存中是连续的内存,删除和插入需要移动内存)
LinkedList 底层使用链表,查询时从头部开始一个一个便利索引,查询效率低,插入是不需要移动内存,只需要改变引用指向即可,所以插入删除效率高。
Set 无序 不可重复 ,根据hashcode和equals 方法判断
HashMap —- HashTable
都存储 key-value ,
1:HashMap可以存null,key或value,HashTable不可以
2: HashMap线程不安全,效率高,HashTable 线程安全,效率低

HashMap:数组加链表存储,
每个节点以Entry形式,
如果不指定长度,默认为16,加载因子默认为0.75,那么阈值就是16*0.75 = 12,当元素HashMap中元素超过12个时,就会触发扩容,
每次扩容默认两倍,
HashMap如果在多线程的情况下发生扩容,可能会导致死循环,所以,如果多线程情况下并且必须使用HsahMap那么就在初始话的时候指定长度,或者阈值 new HashMap(20,1).
entry包含,key,vlaue ,hash,next元素组成,
-1.7 新增节点
当put时,先算出key在数组中的下标(key.hashcode() % 数组长度-1)
然后循环当前数组该下标下的所有元素链表,循环该链表,一一比对当前的key是否和链表中的key是否相同,如果相同,则替换key的value值,同时把旧的value返回。
如果链表中没有找到相同的key,那么给当前链表头部增加一个entry对象,并且当前entry对象的next指针指向链表原始头部的entry对象。
如果key为null的话,默认放到链表的第0位置

*1.8 新增节点

  • 与1.7不同的是:
    Entry对象该为Node对象存储;
    新增的节点会放在链表的尾部;
    如果链表长度达到8,会转换成红黑树存储;
    扩容时,如果下标为0,那么在新的数组中下标不变,如果不为0,那么在新的数组中下标位置为扩容前的数组长度+扩容前的数组下标。

CurrentHashMap 线程安全,效率高。
1.7:原理:(把大的Map分割成N个小的Map–Segment,类似HashMap,给各个小的Map加锁,第一个Map的数据加锁时,不影响第二个Map的使用,使效率提升,默认提升16倍。)
1.8: 对数组节点的链表头部的元素加锁。链表为Node节点

字节流,字符流

字符流传递的是字符,中文汉字
字节流传输的是二进制的字节。
传输的文件比一定包含字符,有可能包含字节,比如,图片,音频,图像,为了考虑通用性,使用字节流

线程

实现方式:
1:继承Thread类
2:实现Runnable接口
java 是单继承,多实现,所以实现Runnable扩展好
启动:
Thread thread = new Thread(继承Thread的对象,或者实现Runnable的对象);
thread.start();
注意:不要用字符串常量加锁,容易产生死锁。
synchronized: 加载方法上,锁的是this,如果方法是static,锁定的是class对象,如果在执行方法是报了异常,虚拟机会自动释放锁。加锁的对象,如果对象属性改变,不影响锁的使用,如果对象的引用变了,则锁的对象发生改变,所以,synchronized锁的是堆内存的对象。保证原子性,可见性
volatile: 解决线程之间的可见性,A,B线程都读取同一个值时,如果B线程修改了值,A线程是无感知的,加上volatile时,主线程修改了值后,会强制所有线程都去重新读取值;
保证可见性,但不保证原子性;
++i 操作不保证原子性。
Atomic:简单的增加或修改数值,可以用AtomicXXX类保证原子性问题,如:(AtomicInteger,AtomicLong)
AtomicInteger a = new AtomicInteger(0);
a.incrementAndGet(); // 这个方法是替代 ++i,保证原子性
if(a.count() < 1000){
//中间不具备原子性
a.incrementAndGet();
} wait(释放锁),object.wait(),object对象上的该线程进行等待,释放锁,其他线程可以获取object对象的锁
notify(不释放锁) 叫醒 object上等待的某个线程,notifyAll 唤醒所有等待线程
sleep(不释放锁)

测试题:两个线程,第一个线程一个自增到10,第二个线程监控,如果加到5就结束第二个线程,第一个继续往下走。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.yahui.fan.zookeeper.ThreadTest;

import java.util.ArrayList;
import java.util.List;

/**
*
* 两个线程,第一个线程一个自增到10,第二个线程监控,如果加到5就结束第二个线程,第一个继续往下走。
* 第一种方式,用wai(),notify(),进行线程通信
*
*/
public class ThreadTest1 {

static List<Integer> i = new ArrayList<>();

public void add(Integer o){
i.add(o);
}

Integer size() {
return i.size();
}


public static void main(String[] args) {


Object object = new Object();

new Thread(() -> {
System.out.println("T2启动。。");
synchronized (object) {
if (i.size() != 5) {
try {
System.out.println("不等于5,T2等待,释放锁");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("T2结束");
System.out.println("T2结束,释放锁,T1继续执行");
object.notify();
}
}).start();

new Thread(() -> {
System.out.println("T1启动。。");
synchronized (object) {
for (int j = 1; j <= 10; j++) {
i.add(j);
System.out.println("add:"+ j);

if (j == 5) {
System.out.println("等于5,唤醒T2");
object.notify();
try {
System.out.println("释放T1当前的锁,让T2执行");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
System.out.println("T1结束。。");
}
}).start();
}
}

运行结果:
T2启动。。
不等于5,T2等待,释放锁
T1启动。。
add:1
add:2
add:3
add:4
add:5
等于5,唤醒T2
释放T1当前的锁,让T2执行
T2结束
T2结束,释放锁,T1继续执行
add:6
add:7
add:8
add:9
add:10
T1结束。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.yahui.fan.zookeeper.ThreadTest;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
*
* 两个线程,第一个线程一个自增到10,第二个线程监控,如果加到5就结束第二个线程,第一个继续往下走。
* 第二种方式,CountDownLatch计数器实现
*
*/
public class ThreadTest2 {

static List<Integer> i = new ArrayList<>();

public void add(Integer o){
i.add(o);
}

Integer size() {
return i.size();
}


public static void main(String[] args) {


CountDownLatch countDownLatch = new CountDownLatch(1);
Object object = new Object();

new Thread(() -> {
System.out.println("T2开始");
if (i.size() != 5) {
try {
System.out.println("长度不等于5,计数器等待,T2等待。");
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("T2结束。");
}
}).start();

try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}

new Thread(() -> {
System.out.println("T1开始");
for (int j = 1; j <= 10; j++) {
i.add(j);
System.out.println("add:" + j);
if (j == 5) {
System.out.println("长度等于5,计数器减一,唤醒T2线程");
countDownLatch.countDown();
}

try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println("T1结束");
}).start();
}
}

运行结果:
T2开始
长度不等于5,计数器等待,T2等待。
T1开始
add:1
add:2
add:3
add:4
add:5
长度等于5,计数器减一,唤醒T2线程
T2结束。
add:6
add:7
add:8
add:9
add:10
T1结束
总结: 两种方式,第二种比较简单易懂,CountDownLatch 不需要对象锁,易扩展,没有像第一个种方式重复的释放锁,执行,过程,效率较高

ReentranLock 必须手动释放锁
tryLock() 尝试获取锁,可指定时间,获取不到锁返回false
ReentranLock lock = new ReentranLock() –非公平锁 性能高
ReentranLock lock = new ReentranLock(true); –公平锁,等待时间长的线程先执行,性能低
wait方法一般搭配while使用,不要用if
在多线程生产消费模式下,唤醒线程用notifyAll(),不要用notify(),可能会造成死锁

实现一个容器,使用生产者消费者进行容器消费,容器总容量为10.

第一种方式实现: 利用Codition 和 Lock 实现,Condition可以等待,唤醒一部分线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

public class ThreadTest3<T> {

final private LinkedList<T> linkedList = new LinkedList();
// 容器最大容量
final private Integer MAX = 10;
private int count = 0;


synchronized void producer(T t){

/**
* while 和wait 结合一起用,为什么不用不用if判断?
* 如果用if,容器到最大后,进行wait等待,这时,如果消费者消费了一个,然后同时唤醒两个生产者线程
* 两个生产者被唤醒,在linkedList.add(t) 的时候,只要一个线程增加进去。另外一个线程在增加就会出现问题
* 用while,当生产者被唤醒的时候,会在判断一次count == MAX,才会继续往下进行
*
*/
while (count == MAX) {
//如果容器达到最大值,生产者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产,当前容器:"+linkedList.size());
linkedList.add(t);
++count;
/**
* 这里为什么用notifyAll 不用nitify?
* 如果用nitify,容器满了之后,如果唤醒的还是生产者线程,调用wait,就造成了线程死锁。
*/
this.notifyAll();
}

synchronized T consumer() {
T t = null;
while (linkedList.size() == 0) {
//如果容器为空,消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费,当前容器:"+linkedList.size());
t = linkedList.removeFirst();
count--;
this.notifyAll();
return t;
}

public static void main(String[] args) {

ThreadTest3<String> threadTest3 = new ThreadTest3();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(threadTest3.consumer());
},"c"+i).start();
}

try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}

for (int i = 0; i < 10; i++) {
new Thread(() -> {
threadTest3.producer(Thread.currentThread().getName()+"");
},"p"+i).start();
}
}

}

第二种方式实现: 利用Codition 和 Lock 实现,Condition可以等待,唤醒一部分线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.yahui.fan.zookeeper.ThreadTest;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class ThreadTest4<T> {

final private LinkedList<T> linkedList = new LinkedList();
// 容器最大容量
final private Integer MAX = 10;
private int count = 0;

private Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition();

void producer(T t){

try {
lock.lock();
while (count == MAX) {
//如果容器达到最大值,生产者等待
producer.await();
}
System.out.println("生产,当前容器:"+linkedList.size());
linkedList.add(t);
++count;
//唤醒所有消费者等待线程
consumer.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}

T consumer() {
T t = null;
try {
lock.lock();
while (linkedList.size() == 0) {
//如果容器为空,消费者等待
consumer.await();
}
System.out.println("消费,当前容器:"+linkedList.size());
t = linkedList.removeFirst();
count--;
//唤醒所有生产者
producer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return t;
}


public static void main(String[] args) {

ThreadTest4<String> threadTest4 = new ThreadTest4();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(threadTest4.consumer());
},"c"+i).start();
}

try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}

for (int i = 0; i < 10; i++) {
new Thread(() -> {
threadTest4.producer(Thread.currentThread().getName()+"");
},"p"+i).start();
}
}

}

ThrealLoacl 当前线程会复制一个变量副本,每个线程互不影响,synchronized 是一个线程完了之后另一个才可以执行,所以,ThreadLocal是空间换时间,synchronized是时间换空间

并发容器

map,set的使用
不同步,不加锁:
HashMap
TreeMap
HashSet
LinkedHashMap
同步,加锁:
并发不高:HashTable,Collections.synchronizeXXX.
并发高:ConcurrentHashMap
高并发,顺序:ConcurrentSkipListMap

ConcurrentHashMap 分为16个小的Map,分段加锁,性能高

Queue

1:高并发,内部加锁 – ConcurrentLinkedQueue 单向队列
offer() 增加,无界队列,如果内存够,一直可以加
poll() 取出第一个并删除
peek() 取出第一个,不删除
2:高并发,阻塞 LinkedBlockingQueue,ArrayBlockingQueue
put() 存,如果队列满了,阻塞等待
take() 取,如果队列空了,阻塞等待
代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.yahui.fan.zookeeper.QueueTest;

import sun.jvm.hotspot.opto.Block;

import java.util.Queue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
* 使用 LinkedBlockingQueue 实现生产消费队列
*
* 无界队列,只要内存够,一直可以put
*/
public class QueueTest {

// 阻塞队列
static BlockingQueue<String> queue = new LinkedBlockingDeque<>();

public static void main(String[] args) {

new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
queue.put("pro:"+i);//如果队列满了,就会阻塞,
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"producer").start();

for (int i = 0; i < 5; i++) {
new Thread(() -> {
while (true) {
try {
System.out.println(Thread.currentThread().getName()+"-"+"con-"+queue.take()); //take 如果队列空了,阻塞
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"consumer").start();
}
}
}

3: ArrayBlockingQueue 有界队列
// 队列里边只能装10个
BlockingQueue queue = new ArrayBlockingQueue(10);
queue.add(“i”); //容器满了会报异常
queue.offer(“i”); //容器满了不保异常,根据返回值判断是否添加成功
queue.offer(“i”;TimeUnit.SECONDS); 隔一段时间添加,加不进去,终止
queue.put(“i”); 容器满了,阻塞等待
4: DelayQueue 无界队列,定时队列,等待时间最长先出
BlockingQueue queue = new DelayQueue();
5: LinkedTransferQueue 如果消费者等待,那生产者queue任务到了不直接扔到队列,而是直接给了消费者queue
LinkdeTransferQueue queue = new LinkedTransferQueue();
queue.transfer(“a”);//生产的消息必须马上处理,不然阻塞
6: SynchronousQueue 同步队列
BlockingQueue queue = new SynchronousQueue();
queue.add(“”);//如果没有消费者,报错
queue.put(“”);//如果没有消费者,阻塞

线程池

Executor
Executors 工具类
ExecutorService -submit(Runnable/Callable) -execute(Runnable)
Runnable 没有返回值
Callable 有返回值,可以抛异常

ThreadPool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.yahui.fan.zookeeper.ThreadPool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPool_01 {

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);

for (int i = 0; i < 6; i++) {
executorService.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
});
}
System.out.println(executorService);

//关闭线程池,等待所有线程都结束关闭
executorService.shutdown();
// 直接关闭线程池,不等待线程
//executorService.shutdownNow();
//线程池的所有任务是否全部执行完毕
System.out.println(executorService.isTerminated());
//线程池是否关闭
System.out.println(executorService.isShutdown());
System.out.println(executorService);

try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(executorService.isTerminated());
System.out.println(executorService.isShutdown());
System.out.println(executorService);

}
}

结果:
//queued tasks = 1 一个等待任务
java.util.concurrent.ThreadPoolExecutor@46ee7fe8[Running, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]
false
true
java.util.concurrent.ThreadPoolExecutor@46ee7fe8[Shutting down, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
pool-1-thread-1
pool-1-thread-2
true
true
//线程池正常关闭,已执行任务列表
java.util.concurrent.ThreadPoolExecutor@46ee7fe8[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 6]

Future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.yahui.fan.zookeeper.ThreadPool;

import com.google.common.collect.Lists;

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

/**
* 使用Future 多线程计算
*/
public class ThreadPool_02 {

public static void main(String[] args) {

//单线程计算
long l2 = System.currentTimeMillis();
List<Integer> prime = getPrime(1, 200000);
long l3 = System.currentTimeMillis();
System.out.println(l3-l2);
System.out.println(prime.size());


//多线程计算
ExecutorService executorService = Executors.newFixedThreadPool(5);
Future<List<Integer>> submit = executorService.submit(new MyTask(1, 60000));
Future<List<Integer>> submit1 = executorService.submit(new MyTask(60001, 100000));
Future<List<Integer>> submit2 = executorService.submit(new MyTask(100001, 140000));
Future<List<Integer>> submit3 = executorService.submit(new MyTask(140001, 180000));
Future<List<Integer>> submit4 = executorService.submit(new MyTask(180001, 200000));


try {
long l = System.currentTimeMillis();
List<Integer> all = new ArrayList<>();
List<Integer> integers = submit.get();
List<Integer> integers1 = submit1.get();
List<Integer> integers2 = submit2.get();
List<Integer> integers3 = submit3.get();
List<Integer> integers4 = submit4.get();
all.addAll(integers);
all.addAll(integers1);
all.addAll(integers2);
all.addAll(integers3);
all.addAll(integers4);
long l1 = System.currentTimeMillis();
System.out.println(l1-l);
System.out.println(all.size());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}



}

static class MyTask implements Callable<List<Integer>> {
int start, end;
MyTask(int start,int end){
this.start = start;
this.end = end;
}


@Override
public List<Integer> call() throws Exception {
return getPrime(start,end);
}
}

private static boolean isPrime(int num){
for (int i = 2; i <= num/2; i++) {
if (num%2 == 0) return false;
}
return true;
}

private static List<Integer> getPrime(int start, int end){
List<Integer> list = Lists.newArrayList();
for (int i = start; i <= end; i++) {
if(isPrime(i)) list.add(i);
}
return list;
}

}

结果:
19
100001
3 100001

线程池种类

//固定个数线程池
–1 ExecutorService executorService = Executors.newFixedThreadPool(5);

1
2
3
4
5
6
7
8
public static ExecutorService newFixedThreadPool(int nThreads) {
//指定线程池大小
return new ThreadPoolExecutor(nThreads, nThreads,
//线程存活时间,永远存在
0L, TimeUnit.MILLISECONDS,
//无界阻塞队列
new LinkedBlockingQueue<Runnable>());
}

//缓存线程池,启动时池中没有线程,有任务过来,就创建,释放的就在线程池中缓存,下个任务来了继续用,如果一直没有任务用,默认60s自动关闭该线程
–2 ExecutorService executorService1 = Executors.newCachedThreadPool();

1
2
3
4
5
6
7
public static ExecutorService newCachedThreadPool() {
//初始线程为0
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
// 有效时间默认60秒
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

// 单例线程池 只有一个线程的线程池,可以保证扔到线程池里的任务是顺序执行
–3 ExecutorService executorService2 = Executors.newSingleThreadExecutor();

1
2
3
4
5
6
7
8
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
//默认只有并且最大线程数只有一个
(new ThreadPoolExecutor(1, 1,
//永远存活
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

// 定时执行
–4 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);

1
2
3
4
5
6
7
8
9
10
11
//方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay, //第一个线程各多长时间开始执行
long period, //每个线程各多久执行
TimeUnit unit); //时间单位

public ScheduledThreadPoolExecutor(int corePoolSize) {
//指定大小,永远存活,使用定时队列
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}

// 精灵线程,每个线程维护自己的队列,自己队列没有任务时,会执行别的线程队列里的任务
–5 ExecutorService executorService1 = Executors.newWorkStealingPool();
默认会根据当前机器的线程来启动相应数量的线程
//查看本机线程数
System.out.println(Runtime.getRuntime().availableProcessors());
// 当任务特别大时,分成多个小线程执行,最后在合并结果
–6 ForkJoinPool forkJoinPool = new ForkJoinPool();

—- 1,2,3,4种线程最终都返回 ThreadPoolExecutor

1
2
3
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());

备注: java8 stream提供多线程计算 parallelStream()

1
2
List<Integer> all = new ArrayList<>();
all.parallelStream().count();