学习笔记:java多线程 JUC之四
list / set / map线程不安全
ArrayList 有序有重复
HashSet HashMap 无序无重复
hashset底层是hashmap,<k,v>中的v是固定常数,hashset的add方法,就是调用hashmapt的put方法
hashmap底层是Node类型的数组+Node类型的链表+红黑树
真正高并发系统,很少用到hashmap
import java.util.*;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 题目:请举例说明集合类线程不安全
*
* 1 故障现象
* java.util.ConcurrentModificationException
*
* 2 导致原因
*
*
* 3 解决方案
* 1 Vector
* 2 Collections.synchronizedList(new ArrayList<>());
* 3 CopyOnWriteArrayList<>();
*
* 4 优化建议(同样的错误,不出现第2次)
*
*
* 笔记:
* 写时复刻
* CopyOnWrite容器即写时复刻容器。往一个容器添加元素的时候,不直接往当前容器Object[]添加,而是先将当前容器Object[]进行Copy,
* 复制出一个新的容器Object[] newElements,然后新的容器Object[] newElements里面添加元素,添加完元素之后,
* 再将原容器的引用指向新的容器setArray(newElements).这样做的好处是可以对CopyOnWrite容器进行并发的读,
* 而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,渡河写不同的容器
*/
public class NotSafeDemo {
public static void main(String[] args) {
//set map 同理
//List<String> list=new ArrayList<>();
//List<String> list= new Vector<>();
//List<String> list= Collections.synchronizedList(new ArrayList<>());
List<String> list= new CopyOnWriteArrayList<>();
Map<String,String> map=new ConcurrentHashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
Callable
获得多线程的方式:
继承Thread类
实现runable接口
实现callable接口
callable接口与runnable接口的区别:
callable有返回值
callable抛异常
落地方法不同 一个run 一个call
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
class MyThread implements Runnable
{
public void run() {
}
}
/**
* 第三种实现多线程方法
*/
class MyThread2 implements Callable<Integer>
{
public Integer call() throws Exception {
System.out.println("......come in here");
try {
TimeUnit.SECONDS.sleep(4);
}catch (InterruptedException e){e.printStackTrace();}
return 1024;
}
}
public class CallableDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException
{
FutureTask futureTask = new FutureTask(new MyThread2());
new Thread(futureTask,"A").start();
System.out.println(Thread.currentThread().getName()+"----计算完成");
System.out.println(futureTask.get());
}
}