下一篇是Java集合的另一个工具类Arrays
当多个线程同时对List对象进行操作时,有两种情况:
①a线程添加元素,b线程删除元素
这时会出现数据错乱的问题,
解决方法: (1)自己使用同步机制控制
(2)把普通集合对象转换为线程安全的集合对象
②a线程遍历元素,b线程添加或者删除元素
这时会出现同步异常的错误(这一点collection那一片有详细介绍)
解决方法:(1)自己使用同步机制控制
(2把吧普通集合转换成线程安全的集合,并且在进行遍历的时候还需要手动同步
方法一:
给两个线程都添加同步代码块:
public class ThreadSafeTest1 {
public static void main(String[] args) {
final List list=new ArrayList();//用final修饰list是内存问题,将在Java程序内存中进行解释
list.add("a");
//开启第一个线程
Thread thread1=new Thread(new Runnable(){
@Override
public void run() {
//第一个线程是遍历集合
//因为遍历集合时候的速度是很快的,所以我们将它放入死循环中,让他一直遍历这样才能与其他的线程发生碰撞
while(true){
//添加同步代码块
synchronized (list) {
Iterator iterator=list.iterator();
while(iterator.hasNext()){
Object str=iterator.next();
System.out.print(str);
try {
Thread.sleep(100);//休眠100ms是为了让其他线程也能运行
} catch (InterruptedException e) {
}
}
System.out.println();
}
}
}
},"a");//该线程明明为a线程
thread1.start();
//开启第二个线程,向集合中添加数据
Thread thread2=new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized (list) {
list.add("c");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
}
},"b");
thread2.start();
}
}
第二种方法:给遍历线程添加同步代码块,修改的线程不需要添加同步代码块
public class ThreadSafeTest2 {
public static void main(String[] args) {
final List list=new ArrayList();
list.add("a");
final List list2=Collections.synchronizedList(list);
//将list转换成一个线程安全的list,这样仅仅需要在遍历的时候添加同步代码块,而在修改的时候不需要添加同步代码块
//开启第一个线程
Thread thread1=new Thread(new Runnable(){
@Override
public void run() {
while(true){
synchronized (list2) {
Iterator iterator=list2.iterator();
while(iterator.hasNext()){
Object str=iterator.next();
System.out.print(str);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
System.out.println();
}
}
}
},"a");
thread1.start();
Thread thread2=new Thread(new Runnable(){
@Override
public void run() {
while(true){
list2.add("c");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
},"b");
thread2.start();
}
}
浙公网安备 33010602011771号