标签:笔试 计数 线程 run 安全 stat 创建 await hashmap
Java面试和笔试中经常会问到
String线程安全StringBuffer线程安全StringBuilder非线程安全
HashMap非线程安全的HashTable线程安全的vector线程安全的
但是接下来会问你,不安全为什么还会用,因为HashMap效率更高,如果想让它变成安全的,加同步锁()
那什么叫线程安全什么叫非线程安全呢?
一、线程
什么叫做线程呢?
建议可以看一下阮一峰大神的博客:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
讲的非常通俗易懂,留言中的内容也要看,因为是转载的,有很多地方值得商榷。
二、线程安全和非线程安全
当多个线程同时操作同一个对象,修改某一个属性的时候,不会发生问题就称之为“线程安全”
可能会出现问题,就是“非线程安全的”
比如说ArrayList和vector来说
在主线程中,new了一个ArrayList线程,现在开100个线程,每个线程向arraylist中存放100个元素,最后ArrayList中有多少个对象,10000?
先创建一个线程类(另外一篇文章会总结学习一下线程的三种实现方式)
1 class MyThread implements Runnable 2 { 3 private List<Object> list; 4 5 private CountDownLatch countDownLatch; 6 7 public MyThread(List<Object> list, CountDownLatch countDownLatch) 8 { 9 this.list = list; 10 this.countDownLatch = countDownLatch; 11 } 12 13 public void run() 14 { 15 // 每个线程向List中添加100个元素 16 for(int i = 0; i < 100; i++) 17 { 18 list.add(new Object()); 19 } 20 21 // 完成一个子线程 22 countDownLatch.countDown(); 23 } 24 }
1 package threadTest; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.concurrent.CountDownLatch; 6 7 public class Test { 8 public static void test() 9 { 10 // 用来测试的List 11 List<Object> list = new ArrayList<Object>(); 12 13 // 线程数量(1000) 14 int threadCount = 1000; 15 16 // 用来让主线程等待threadCount个子线程执行完毕 17 CountDownLatch countDownLatch = new CountDownLatch(threadCount); 18 19 // 启动threadCount个子线程 20 for(int i = 0; i < threadCount; i++) 21 { 22 Thread thread = new Thread(new MyThread(list, countDownLatch)); 23 thread.start(); 24 } 25 26 try 27 { 28 // 主线程等待所有子线程执行完成,再向下执行 29 countDownLatch.await(); 30 } 31 catch (InterruptedException e) 32 { 33 e.printStackTrace(); 34 } 35 36 // List的size 37 System.out.println(list.size()); 38 } 39 public static void main(String[] args) 40 { 41 // 进行10次测试 42 for(int i = 0; i < 10; i++) 43 { 44 test(); 45 } 46 } 47 48 }
最后结果:
99799
99814
99765
100000
99868
99830
100000
99915
99858
99830
但是有时候会产生异常
这就是所谓的非线程安全
接下来换成线程安全的vector
将test里边的ArrayList换成vector
List<Object> list = new ArrayList<Object>();
List<Object> list = new Vector<Object>();
100000
100000
100000
100000
100000
100000
100000
100000
100000
100000
输出结果
在多试几次,还是一样的结果,因为vector是线程安全的,换成LinkedList结果和ArrayList类似,因为LinkedList也是非线程安全的
三、如何取舍
当存在多个线程操作同一对象的时候,就采用vector等线程安全的,如果不涉及,就采用ArrayList等,因为效率高
如果想要用ArrayList也可以,线程安全必须要使用很多synchronized关键字来同步控制,加同步锁
List<Object> list = Collections.synchronizedList(new ArrayList<Object>());
synchronized关键字同步,但是这样会降低效率
另外一种,实在方法前边用synchronized修饰方法
一个计数器类
class Counter { private int count = 0; public int getCount() { return count; } public void addCount() { count++; } }
创建线程类
1 class MyThread implements Runnable 2 { 3 private Counter counter; 4 5 private CountDownLatch countDownLatch; 6 7 public MyThread(Counter counter, CountDownLatch countDownLatch) 8 { 9 this.counter = counter; 10 this.countDownLatch = countDownLatch; 11 } 12 13 public void run() 14 { 15 // 每个线程向Counter中进行10000次累加 16 for(int i = 0; i < 10000; i++) 17 { 18 counter.addCount(); 19 } 20 21 // 完成一个子线程 22 countDownLatch.countDown(); 23 } 24 }
主线程
1 public class Main 2 { 3 public static void main(String[] args) 4 { 5 // 进行10次测试 6 for(int i = 0; i < 10; i++) 7 { 8 test(); 9 } 10 } 11 12 public static void test() 13 { 14 // 计数器 15 Counter counter = new Counter(); 16 17 // 线程数量(1000) 18 int threadCount = 1000; 19 20 // 用来让主线程等待threadCount个子线程执行完毕 21 CountDownLatch countDownLatch = new CountDownLatch(threadCount); 22 23 // 启动threadCount个子线程 24 for(int i = 0; i < threadCount; i++) 25 { 26 Thread thread = new Thread(new MyThread(counter, countDownLatch)); 27 thread.start(); 28 } 29 30 try 31 { 32 // 主线程等待所有子线程执行完成,再向下执行 33 countDownLatch.await(); 34 } 35 catch (InterruptedException e) 36 { 37 e.printStackTrace(); 38 } 39 40 // 计数器的值 41 System.out.println(counter.getCount()); 42 } 43 }
9760282
9999073
9999969
9990000
9998743
9965715
9990000
9994370
9990945
9993745
创建一个线程安全的计数器
class Counter { private int count = 0; public int getCount() { return count; } public synchronized void addCount() { count++; } }
10000000
10000000
10000000
10000000
10000000
10000000
10000000
10000000
10000000
输出结果
标签:笔试 计数 线程 run 安全 stat 创建 await hashmap
原文地址:http://www.cnblogs.com/Darius-Bennett/p/7858063.html