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("-------------------------------------------------"); } }
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,并发时会出现问题。 Apache common-lang提供的DateFormatUtils.format方法比JDK提供的SimpleDataFormat.format性能高出 149.82%。 推荐使用ThreadLocal方式绑定SimpleDateFormat到每一个线程中,这样性能较好。 整体性能对比: ThreadLocal方式 > DateFormatUtils.format > 每次建立SimpleDataFormat.format
apache
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在添加元素时,若是数组长度不够用时,须要扩张数组长度,而后再添加元素。在并发状况下,会致使数据不正确。如下代码示例: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(); } }