内容正在完善中……线程池inghtml
ArrayList:数组实现,按下标访问效率高(随机访问),增删操做费事java
Victor:在ArrayList基础上添加了线程安全特性,效率下降面试
LinkedList:双向链表实现,增删效率高,不支持下标访问(随机访问),只能顺序查找express
HashSet:哈希表实现,查找效率高 O(1),无序ubuntu
LinkedHashSet:双向链表维护元素的插入顺序,查询效率高,有序api
TreeSet:红黑树实现,有序( 甚至拿来排序orz ),查找效率较低 O(logN)数组
存值: put(K key, V value))
安全
经过key取value: get(K key)
,返回valuebash
取全部keys: keySet()
,返回key的集合并发
遍历: (常考)
private static String keySetTest(HashMap<Integer, String> hashMap){
StringBuilder result = new StringBuilder("KeySetTest: ");
for ( Integer i : hashMap.keySet() ){
result.append(i).append(": ").append(hashMap.get(i));
}
return result.toString();
}
复制代码
private static String entrySetTest(HashMap<Integer, String> hashMap){
StringBuilder result = new StringBuilder("EntrySetTest: ");
for ( Map.Entry<Integer, String> entry: hashMap.entrySet() ){
result.append(entry.getKey()).append(": ").append(entry.getValue());
}
return result.toString();
}
复制代码
private static String iteratorTest(HashMap<Integer, String> hashMap){
StringBuilder result = new StringBuilder("IteratorTest: ");
Iterator iterator = hashMap.entrySet().iterator();
while( iterator.hasNext() ){
Map.Entry entry = (Map.Entry) iterator.next();
result.append(entry.getKey()).append(": ").append(entry.getValue());
}
return result.toString();
}
复制代码
注意:经检验这就是EntrySet同样的作法……idea会把此种方案视为可优化为foreach循环的可优化点
private static String foreachIteratorTest(HashMap<Integer, String> hashMap){
StringBuilder result = new StringBuilder("ForeachIteratorTest: ");
for ( Map.Entry<Integer, String> entry: hashMap.entrySet() ) {
result.append(entry.getKey()).append(": ").append(entry.getValue());
}
return result.toString();
}
复制代码
private static String iteratorWithoutTypeTest(HashMap<Integer, String> hashMap){
StringBuilder result = new StringBuilder("IteratorWithoutTypeTest: ");
Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();
while( iterator.hasNext() ){
Map.Entry entry = iterator.next();
result.append(entry.getKey()).append(": ").append(entry.getValue());
}
return result.toString();
}
复制代码
private static String foreachIteratorWithoutTypeTest(HashMap<Integer, String> hashMap){
StringBuilder result = new StringBuilder("ForeachIteratorWithoutTypeTest: ");
for (Map.Entry entry : hashMap.entrySet()) {
result.append(entry.getKey()).append(": ").append(entry.getValue());
}
return result.toString();
}
复制代码
测速: 目前测速方案致使结果波动验证,仍在调整中……
public static void main(String[] args){
HashMap<Integer, String> hashMap = new HashMap<>();
for (int i = 0; i < 1000000; i++) {
hashMap.put(i, String.valueOf(i));
}
for (int i = 1; i <= 6; i++) {
System.out.println(runTestWithClock(i, hashMap).substring(0, 30));
}
}
private static String runTestWithClock(int n, HashMap<Integer, String> hashMap){
String result = null;
long clock = System.currentTimeMillis();
long timer = 0;
System.out.println("--------"+n+"-------");
switch (n){
case 1:
result = keySetTest(hashMap);
break;
case 2:
result = entrySetTest(hashMap);
break;
case 3:
result = iteratorTest(hashMap);
break;
case 4:
result = foreachIteratorTest(hashMap);
break;
case 5:
result = coolerIteratorTest(hashMap);;
break;
case 6:
result = foreachCoolerIteratorTest(hashMap);
break;
}
timer = System.currentTimeMillis() - clock ;
System.out.println("Timer: "+timer);
return result;
}
复制代码
--------1-------
Timer: 1232 1234 1207
KeySetTest: 0: 01: 12: 23: 34:
--------2-------
Timer: 96 112 100
EntrySetTest0: 01: 12: 23: 34:
--------3-------
Timer: 127 120 109
IteratorTest: 0: 01: 12: 23: 3
--------4-------
Timer: 98 91 111
ForeachIteratorTest: 0: 01: 12
--------5-------
Timer: 112 99 104
CoolerIteratorTest: 0: 01: 12:
--------6-------
Timer: 105 106 122
ForeachCoolerIteratorTest: 0:
复制代码
method | 1 | 2 | 3 |
---|---|---|---|
KeySet | 1232 | 1234 | 1207 |
EntrySet | 96 | 112 | 100 |
Iterator | 127 | 120 | 109 |
ForeachIterator | 98 | 91 | 111 |
CoolerIterator | 112 | 99 | 104 |
ForeachCoolerIterator | 105 | 106 | 122 |
结果波动性比较大,安全起见从新制定测试计划
先对①和②进行验证
size | 2000k | 1500k | 1000k | 100k | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
times | 1 | 2 | 3 | 4 | 5 | 1 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
KeySet | 2315 | 2271 | 2303 | 2328 | 2258 | 813 | 816 | 819 | 1232 | 1234 | 1207 | 25 | 30 | 25 |
EntrySet | 203 | 1010 | 201 | 991 | 201 | 735 | 738 | 745 | 96 | 112 | 100 | 23 | 25 | 23 |
Iterator | 178 | 155 | 165 | 165 | 170 | 180 | 173 | 188 | 127 | 120 | 109 | 24 | 26 | 24 |
ForeachIterator | 986 | 147 | 983 | 194 | 971 | 138 | 134 | 137 | 98 | 91 | 111 | 27 | 27 | 37 |
IteratorWithoutType | 185 | 187 | 179 | 162 | 169 | 134 | 122 | 130 | 112 | 99 | 104 | 18 | 19 | 19 |
ForeachIteratorWithoutType | 183 | 188 | 180 | 156 | 150 | 145 | 112 | 121 | 105 | 106 | 122 | 19 | 21 | 20 |
表格渲染结果不佳,另附https://paste.ubuntu.com/p/VKmyxsGbdh/
由此表大体能够认为在这次测试中,HashMap<Integer,String>存储简单类型的k-v值:
猜测:
进一步推测:
验证:
private static String entrySetTest(HashMap<Integer, String> hashMap) {
StringBuilder result = new StringBuilder("EntrySetTest: ");
Iterator var2 = hashMap.entrySet().iterator();
while(var2.hasNext()) {
Entry<Integer, String> entry = (Entry)var2.next();
result.append(entry.getKey()).append(": ").append((String)entry.getValue());
}
return result.toString();
}
复制代码
private static String foreachIteratorTest(HashMap<Integer, String> hashMap) {
StringBuilder result = new StringBuilder("ForeachIteratorTest: ");
Iterator var2 = hashMap.entrySet().iterator();
while(var2.hasNext()) {
Entry<Integer, String> entry = (Entry)var2.next();
result.append(entry.getKey()).append(": ").append((String)entry.getValue());
}
return result.toString();
}
复制代码
果真是同样的,这些for-each是基于iterator实现的
结论:
public class RunnableThreadTest implements Runnable{
@Override
public void run() {
// do sth.
}
}
复制代码
运行:
public static void main(String[] args) {
RunnableThreadTest threadTest = new RunnableThreadTest();
Thread thread = new Thread(threadTest);
thread.start();
}}
复制代码
class ThreadTestExtentsThread extends Thread{
public static void main(String[] args) {
ThreadTestExtentsThread testExtentsThread = new ThreadTestExtentsThread();
testExtentsThread.start();
}
}
复制代码
class CallableThreadTest implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Integer result = 123;
// do sth.
return result;
}
}
复制代码
使用:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallableThreadTest threadTest = new CallableThreadTest();
// 指派一项要完成的任务,目标得到物件类型为Integer
FutureTask<Integer> task = new FutureTask<>(threadTest);
// 把task交托给thread
Thread thread007 = new Thread(task);
// 特工007开始执行任务:D (Target is locked)
thread007.start();
// 得到任务执行结果
Integer resultOfTask = task.get();
System.out.println(resultOfTask);
}
复制代码
咳咳,使用007来理解FutureTask可能更清晰一些XD
唔,干脆发挥一下神盾局AOS……
// 众所周知神盾局致力于寻找o-8-4,随叫随到:D
class AOS implements Callable<O84>{
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 固然,这事儿运做得先有神盾局
AOS aos = new AOS();
// 还须要有任务
FutureTask<O84> mission = new FutureTask<>(aos);
// 任务须要指派特工去完成
Thread agent = new Thread(mission);
// 特工开始执行任务
agent.start();
/** 任务执行中 **/
// 获取行动结果-o84
O84 target = mission.get();
System.out.println(target);
}
@Override
public O84 call() throws Exception {
O84 target = new O84();
// 行动中
// Find out what is o84
// Like Thor's hammer XD
return target;
}
}
class O84 {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
复制代码
这样一想是否是清楚了不少咧:D (别趁如今回去看一次吼,时间瞬间……等等怎么一天过去了)
new Thread(() -> {
// do sth.
}).start();
复制代码
实际是用runnable的:
new Thread(new Runnable() {
@Override
public void run() {
// do sth.
}
}).start();
复制代码
public class WaitNotifyTest {
private static Object goods = null;
private void waitNotify() throws InterruptedException {
new Thread(() -> {
synchronized (this){
while( goods == null ){
try{
System.out.println("1. [Consumer]Waiting");
this.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
System.out.println("3. [Consumer]Done");
}).start();
Thread.sleep(1000L);
new Thread(()->{
goods = new Object();
synchronized (this){
this.notifyAll();
System.out.println("2. [Consumer]NotifyAll");
}
}).start();
}
public static void main(String[] args) throws InterruptedException {
new WaitNotifyTest().waitNotify();
}
}
复制代码
import java.util.concurrent.locks.LockSupport;
public class ParkUnparkTest {
private static Object goods = null;
public static void main(String[] args) throws InterruptedException {
new ParkUnparkTest().parkUnpark();
}
private void parkUnpark() throws InterruptedException {
Thread consumerThread = new Thread( ()->{
while( goods == null ){
System.out.println("1. [Consumer]Park");
LockSupport.park();
}
System.out.println("3. [Consumer]Done");
});
consumerThread.start();
Thread.sleep(1000L);
goods = new Object();
LockSupport.unpark(consumerThread);
System.out.println("2. [Consumer]Unpark");
}
}
复制代码
测试类
public class ThreadPoolTest {
public static void main(String[] args) throws Exception {
ThreadPoolTest threadPoolTest = new ThreadPoolTest();
threadPoolTest.threadPoolExecutorTest01();
threadPoolTest.threadPoolExecutorTest02(); // 分别执行请自行添加注释
threadPoolTest.threadPoolExecutorTest03();
}
private void submitMission(ThreadPoolExecutor threadPoolExecutor) throws Exception{
for (int i = 0; i < 15; i++) {
int n = i;
threadPoolExecutor.submit(() -> {
// 提交15项任务,每项需执行3秒
try{
System.out.println("Start: "+n);
Thread.sleep(3000L);
System.out.println("Finish: "+n);
}catch (InterruptedException e){
e.printStackTrace();
}
});
System.out.println("Submitted: "+i);
}
// 在提交完任务到任务执行完成之间,输出线程池状态
Thread.sleep(500L);
System.out.println("PoolSize: "+threadPoolExecutor.getPoolSize());
System.out.println("QueueSize: "+threadPoolExecutor.getQueue().size());
// 预期为5项任务所有执行完成以后,输出线程池状态
Thread.sleep(15000L);
System.out.println("PoolSize: "+threadPoolExecutor.getPoolSize());
System.out.println("QueueSize: "+threadPoolExecutor.getQueue().size());
}
}
复制代码
测试01代码:
private void threadPoolExecutorTest01() throws Exception {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
5, // corePoolSize
10, // maximumPoolSize
5, // keepAliveTime
TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>());
submitMission(tpe);
}
复制代码
测试01结果:
Submitted: 0
Start: 0
Submitted: 1
Submitted: 2
Start: 1
Submitted: 3
Start: 2
Submitted: 4 ← 5项任务提交
Start: 3
Start: 4 ← 5项任务启动
Submitted: 5
Submitted: 6
Submitted: 7
Submitted: 8
Submitted: 9
Submitted: 10
Submitted: 11
Submitted: 12
Submitted: 13
Submitted: 14 ← 全部任务提交
PoolSize: 5 ← 池子中线程数
QueueSize: 10 ← 等待队列中任务数量:10
Finish: 4
Finish: 1
Finish: 3
Finish: 0
Finish: 2 ← 5项任务结束
Start: 8
Start: 7
Start: 6
Start: 5
Start: 9 ← 后5项任务启动
Finish: 7
Finish: 8
Finish: 5
Finish: 6
Finish: 9 ← 后5项任务结束
Start: 13
Start: 12
Start: 11
Start: 10
Start: 14 ← 最后5项任务启动
Finish: 12
Finish: 13
Finish: 10
Finish: 14
Finish: 11 ← 最后5项任务结束
PoolSize: 5
QueueSize: 0 ← 等待队列为空
复制代码
测试02代码:
private void threadPoolExecutorTest02() throws Exception {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
5, // corePoolSize
10, // maximumPoolSize
5, // keepAliveTime
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(3), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
System.err.println("Mission rejected");
}
});
submitMission(tpe);
}
复制代码
测试02结果:
Submitted: 0
Start: 0
Submitted: 1
Submitted: 2
Start: 1
Start: 2
Submitted: 3
Start: 3
Submitted: 4 ← 5项任务提交
Submitted: 5
Submitted: 6
Start: 4 ← 5项任务启动
Submitted: 7
Submitted: 8
Submitted: 9
Start: 8
Submitted: 10
Start: 9
Submitted: 11
Start: 10
Submitted: 12 ← 等待队列中任务数量:3
Start: 11
Mission rejected ← 此处提交数已经达到14>最大线程数10+等待队列容量3,拒绝任务
Submitted: 13
Mission rejected ← 同理拒绝任务
Start: 12
Submitted: 14
PoolSize: 10 ← 已经达到池子最大线程数,可是核心仍是5
QueueSize: 3
Finish: 0
Finish: 4
Finish: 1
Finish: 3
Finish: 2 ← 核心数量5因此先执行5项任务
Start: 7 ← 开始取出等待队列中的任务
Start: 5
Start: 6 ← 取完等待队列中的任务
Finish: 10
Finish: 11
Finish: 9
Finish: 8
Finish: 12
Finish: 5
Finish: 7
Finish: 6 ← 执行结束,不包含任务14和15,他们被rejected了
复制代码
以上两则测试演示了ThreadPoolExecutor中池子最大线程数和等待队列的效果,注意点:
简图:
等待队列可视为右方的蓄水箱,不设定大小则至关于无限积水,左侧水箱maxSize永远不会满; 可是若是等待队列有容量,左侧水箱天然也就会出现溢出到maxSize的状况(即num-capacity-corePoolSize需≤maximumPoolSize)
复制代码