多線程開發

字符串拼接

String.format、字符串拼接、StringBuffer性能對比: StringBuffer > 字符串拼接 > String.format。java

public class StringAppendMultiThread {

	public static void main(String[] args) {
		method1(100000000);
	}

	static String success_code = "0";

	static byte splite = 0x01;

	private static void method1(long times) {
		String resultMsg = "";
		long time1 = System.nanoTime();
		for (long i = 0; i < times; i++) {
			resultMsg = String.format("ErrorCode=%s%cErrorMsg=心跳包接收成功%c", success_code, splite, splite);
		}
		long time2 = System.nanoTime();
		System.out.println("StringFormat:" + (time2 - time1) / times + "ns");

		long time3 = System.nanoTime();
		for (long i = 0; i < times; i++) {
			resultMsg = "ErrorCode=" + success_code + splite + "ErrorMsg=心跳包接收成功" + splite;
		}
		long time4 = System.nanoTime();
		System.out.println("String add:" + (time4 - time3) / times + "ns");

		StringBuffer sb = null;
		long time5 = System.nanoTime();
		for (long i = 0; i < times; i++) {
			sb = new StringBuffer();
			resultMsg = sb.append("ErrorCode=").append(success_code).append(splite).append("ErrorMsg=心跳包接收成功")
					.append(splite).toString();
		}
		long time6 = System.nanoTime();
		System.out.println("StringBuffer add:" + (time6 - time5) / times + "ns");
		System.out.println("-------------------------------------------------");
	}
}

System.currentTimeMillis()

native方法,內部使用了jvm鎖。在併發狀況下,性能低下,且在windows與linux系統下性能表現一不樣,在Linux系統下運行性能更慢,與操做系統底層運行機制有關。linux

public class SystemCurrentTimeMultiThread {

	public static void main(String[] args) {
	for (int i = 0; i < 10; i++) {
			new Thread() {
				@Override
				public void run() {
					test_milli_speed();
				}
			}.start();
		}
	}

	static void test_milli_speed() {
		long sum = 0;
		int N = 100000000;
		long t1 = System.currentTimeMillis();
		for (int i = 0; i < N; i++)
			sum += System.currentTimeMillis();
		long t2 = System.currentTimeMillis();
		System.out.println(Thread.currentThread().getName() + "=》Sum = " + sum + "; time = " + (t2 - t1) + "; or " + (t2 - t1) * 1.0E6 / N + " ns / iter");
	}
}

SimpleDateFormat

非線程安全,多線程共享同一SimpleDateFormat,併發時會出現問題。 Apache common-lang提供的DateFormatUtils.format方法比JDK提供的SimpleDataFormat.format性能高出 149.82%。 推薦使用ThreadLocal方式綁定SimpleDateFormat到每一個線程中,這樣性能較好。 整體性能對比: ThreadLocal方式 > DateFormatUtils.format > 每次建立SimpleDataFormat.formatapache

public class SimpleDataFormatPerfTest {

	private static final int circleNum = 10000000;
	private static String pattern = "yyyy-MM-dd HH:mm:ss";
	private Executor testExecutor = Executors.newFixedThreadPool(64);

	private static ThreadLocal<SimpleDateFormat> simpleDateFormatProvider = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		}
	};

	public static void main(String[] args) {
		SimpleDataFormatPerfTest test = new SimpleDataFormatPerfTest();

		SimpleDateFormat format = new SimpleDateFormat(pattern);
		System.out.println("jdkSimpleDataFormat date format: " + format.format(new Date()));
		System.out.println("apacheSimpleDataFormat date format: " + DateFormatUtils.format(new Date(), pattern));
		System.out.println( "threadLocalSimpleDataFormat date format: " + simpleDateFormatProvider.get().format(new Date()));

		// 1 Jdk SimpleDateFormat
		test.jdkSimpleDataFormatPerf();
		// 2 Apache common-lang SimpleDateFormat
		test.apacheSimpleDataFormatPerf();
		// 3 ThreadLocal SimpleDateFormat
		test.threadLocalSimpleDataFormatPerf();
	}

	public void jdkSimpleDataFormatPerf() {
		long t1 = System.currentTimeMillis();
		for (int i = 0; i < circleNum; i++) {
			SimpleDateFormat format = new SimpleDateFormat(pattern);
			format.format(new Date());
		}
		long t2 = System.currentTimeMillis();
		System.out.println("originSimpleDataFormat cost time: " + (t2 - t1));

	}

	public void apacheSimpleDataFormatPerf() {
		long t1 = System.currentTimeMillis();
 		for (int i = 0; i < circleNum; i++) {
 			DateFormatUtils.format(new Date(), pattern);
 		}
 		long t2 = System.currentTimeMillis();
 		System.out.println("apacheSimpleDataFormat cost time: " + (t2 - t1));

 	}

 	public void threadLocalSimpleDataFormatPerf() {
 		long t1 = System.currentTimeMillis();
 		for (int i = 0; i < circleNum; i++) {
 			simpleDateFormatProvider.get().format(new Date());
		}
		long t2 = System.currentTimeMillis();
		System.out.println("threadLocalSimpleDataFormat cost time: " + (t2 - t1));
	}
}

ArrayList在多線程下數據丟失

ArrayList是一個非線程安全的集合類,底層數據結構是數組實現的,而數組是固定長度的,因此在ArrayList在添加元素時,若是數組長度不夠用時,須要擴張數組長度,而後再添加元素。在併發狀況下,會致使數據不正確。如下代碼示例:1000個線程,訪問同一個ArrayList對象,每一個線程往List中插入100個元素,最後,ArrayList中的元素個數並不是1000*100,而會出現各類結果:99749,99453...。具體代碼以下:windows

package com.yss.sofa.demo.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ArralyListMultThread {
	public static void main(String[] args) {
		// 用來測試的ArrayList
		List<Object> list = new ArrayList<Object>();

		// 線程數量(1000)
		int threadCount = 1000;

		// 用來讓主線程等待threadCount個子線程執行完畢
		CountDownLatch countDownLatch = new CountDownLatch(threadCount);

		// 啓動threadCount個子線程
		for (int i = 0; i < threadCount; i++) {
			Thread thread = new Thread(new MyThread(list, countDownLatch));
			thread.start();
		}
		try {
			// 主線程等待全部子線程執行完成,再向下執行
			countDownLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(list.size());
	}
}

class MyThread implements Runnable {
	List<Object> list;
	CountDownLatch countDownLatch;

	MyThread(List<Object> list, CountDownLatch countDownLatch) {
		this.list = list;
		this.countDownLatch = countDownLatch;
	}

	public void run() {
		for (int i = 0; i < 100; i++) {
			list.add(new Object());
		}
		countDownLatch.countDown();
	}
}
相關文章
相關標籤/搜索