多线程开发

字符串拼接

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();
	}
}
相关文章
相关标签/搜索