一. 先上結論
- 當多個線程共用一個Runnable實現類的對象
numRunnable
時(Thread thread = new Thread(numRunnable,"thread"+i)
),Runnable實現類的成員變量是線程不安全的!
二. 問題復現
public class Test {
public static void main(String[] args) {
int total = insertDataToTN(100,1);
System.out.println("總:"+total);
}
public static int insertDataToTN(int threadCount, final int cycleCount){
class NumRunnable implements Runnable{
int totalSum = 0;
public void run(){
for(int i = 0 ; i<10000;i++){
totalSum++;
}
}
}
NumRunnable numRunnable = new NumRunnable();
List<Thread> threads = new ArrayList<Thread>();
for(int i=0;i<threadCount;i++) {
Thread thread = new Thread(numRunnable,"thread"+i);
thread.start();
threads.add(thread);
}
for(Thread tThread:threads){
try {
tThread.join();
}catch (Exception e){
e.printStackTrace();
}
}
return numRunnable.totalSum;
}
}
三. 解決方法
1. 法1:使用原子類AtomicInteger
public class Test {
public static void main(String[] args) {
AtomicInteger a = insertDataToTN(100,1);
System.out.println(a);
}
public static AtomicInteger insertDataToTN(int threadCount, final int cycleCount){
class NumRunnable implements Runnable{
AtomicInteger totalSum = new AtomicInteger(0);
public void run(){
for(int i = 0 ; i<10000;i++){
totalSum.addAndGet(1);
}
}
}
NumRunnable numRunnable = new NumRunnable();
List<Thread> threads = new ArrayList<Thread>();
for(int i=0;i<threadCount;i++) {
Thread thread = new Thread(numRunnable,"thread"+i);
thread.start();
threads.add(thread);
}
for(Thread tThread:threads){
try {
tThread.join();
}catch (Exception e){
e.printStackTrace();
}
}
return numRunnable.totalSum;
}
}
2. 法2:使用synchronized關鍵字
public class Test {
public static void main(String[] args) {
int total = insertDataToTN(100,1);
System.out.println("總:"+total);
}
public static int insertDataToTN(int threadCount, final int cycleCount){
class NumRunnable implements Runnable{
int totalSum = 0;
public void run(){
for(int i = 0 ; i<10000;i++){
add();
}
}
public synchronized void add(){
totalSum++;
}
}
NumRunnable numRunnable = new NumRunnable();
List<Thread> threads = new ArrayList<Thread>();
for(int i=0;i<threadCount;i++) {
Thread thread = new Thread(numRunnable,"thread"+i);
thread.start();
threads.add(thread);
}
for(Thread tThread:threads){
try {
tThread.join();
}catch (Exception e){
e.printStackTrace();
}
}
return numRunnable.totalSum;
}
}