Java Concurrence

仅总结目前已掌握的关于Java并发相关的知识点。

 

Part1, Basics

1, 多线程的作用,提高系统整体性能(IO Blocking,充分利用多核CPU)

2,Java如何实现多线程(继承 Thread,实现Runnable,实现Callable<E>)

3,Thread related methods(start,join,sleep,yield,interrupt,setDaemon,setPriority,setName,...)

4,多线程下如何保护临界资源(即线程互斥,引入问题示例:多个线程对计数器的累加)
可见性,有序性,内存模型(主内存,工作内存),volatile 和 synchronized 的使用,(读-读,写-读,写-写)

5,wait,notify,notifyall(线程同步),实现一个简单的BlockingQueue

6,ThreadLocal的使用,原理,为什么能解决临界资源访问冲突问题,HibernateSessionFactory

7,DeadLock,如何避免DeadLock,如何检查是否有DeadLock(jstack,jconsole,...)

 

Part2, Advanced
1,线程池的使用,能够解决什么问题(重复创建线程的开销,合理规划子任务并发执行的线程数量),  
Executors.newFixedThreadPool(),  
Executors.newCachedThreadPool(),  
Executors.newScheduledThreadPool(),  
Executors.newSingleThreadPool()

2,Future, FutureTask  
Future: 获取线程执行结果,阻塞等待 
FutureTask,对Runnable和Callable进行封装,阻塞等待

3,ReentrantLock,可重入,公平锁与非公平锁,使用格式(try-finally),时间锁等待,中断锁等待,CAS原语等

4,ReentrantReadWriteLock,使用场景及优点,实现自定义ConcurrentHashMap,读写分离

5,Condition的使用,优点,对BlockingQueue改写

6,Semaphore(信号量,停车场系统),CountDownLatch(确定所有子任何何时全部完成),CyclicBarrier(确定所有子任务同时开始,子任务需相互等待)

7,AtomicInteger,AtomicLong,累加器,不用手动加锁

8,synchronized与ReentrantLock的比较
synchronized:语言级别的支持,不用手动release锁对象,在一些简单环境下使用
ReentrantLock:非语言级别的支持,需手动release锁对象,使用更灵活(跨方法lock和unlock锁对象),功能更强大(时间锁等待,中断锁等待,公平和非公平锁,Condition的使用,读写锁的支持等),在synchronized无法满足需求的场景下使用

9,wait/notify/notifyAll与Condition的比较 
wait/notify/notifyAll:任何对象都有的方法,用于简单场景下线程的同步,但控制粒度较粗(以锁对象为单位)
Condition:基于ReentrantLock锁对象创建的条件对象,用于复杂场景下线程的同步,能自定义控制粒度,更灵活

 

相关示例,某些示例需要在debug模式下结合断点运行,

package com.my.study.concurrent;

public class TestAddNumber {
	private static long num = 0;

	public static void main(String[] args) {
		Thread t1 = new Thread(new SubClass());
		Thread t2 = new Thread(new SubClass());

		t1.start();
		t2.start();

		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("num = " + num);
	}

	private static class SubClass implements Runnable {

		@Override
		public void run() {
			//synchronized (TestAddNumber.class) {
				for (long i = 1; i <= 100000000; i++) {
					num += i;
				}
			//}
		}
	}
}

package com.my.study.concurrent;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class TestAtomic {
	public static void main(String[] args) {
		testAtomicInteger();
		// testAtomicLong();
	}

	private static void testAtomicInteger() {
		AtomicInteger ai = new AtomicInteger();
		for (int i = 0; i < 10; i++) {
			System.out.println(ai.getAndIncrement());
		}
	}

	private static void testAtomicLong() {
		AtomicLong al = new AtomicLong();
		for (int i = 0; i < 10; i++) {
			System.out.println(al.getAndIncrement());
		}
	}
}

package com.my.study.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestCallable {

	private static ExecutorService service = Executors.newFixedThreadPool(10);

	public static void main(String[] args) {
		testStartCallableThread();
		// testStartMultiCallableThread();

		service.shutdown();
	}

	private static void testStartCallableThread() {
		CallableClass clazz = new CallableClass(1);
		Future<String> resultFuture = service.submit(clazz);
		try {

			System.out.println("Try to get result...");

			String result = resultFuture.get();

			System.out.println("Result is: " + result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void testStartMultiCallableThread() {
		List<Callable<String>> tasks = new ArrayList<Callable<String>>();

		for (int i = 0; i < 5; i++) {
			tasks.add(new CallableClass(i));
		}

		try {
			List<Future<String>> results = service.invokeAll(tasks);
			for (Future<String> result : results) {
				System.out.println("Result is: " + result.get());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static class CallableClass implements Callable<String> {

		private int num;

		public CallableClass(int num) {
			this.num = num;
		}

		@Override
		public String call() throws Exception {
			try {
				System.out.println("Begin call()." + num);
				Thread.sleep(1000 * num);
				System.out.println("End call()." + num);
				return num + ",OK";
			} catch (Exception e) {
				e.printStackTrace();
				throw e;
			}
		}
	}
}

package com.my.study.concurrent;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class TestCondition {
	private static MyBlockingQueue<Car> carQueue = new MyBlockingQueue<Car>(6);

	public static void main(String[] args) {
		Productor[] productors = new Productor[10];
		for (int i = 0; i < productors.length; i++) {
			productors[i] = new Productor("P" + i, carQueue);
		}
		for (Productor p : productors) {
			new Thread(p).start();
		}

		Consumer[] consumers = new Consumer[1];
		for (int i = 0; i < consumers.length; i++) {
			consumers[i] = new Consumer("S" + i, carQueue);
		}
		for (Consumer c : consumers) {
			new Thread(c).start();
		}
	}

	private static class Productor implements Runnable {

		private String productorName;
		private MyBlockingQueue<Car> queue;

		public Productor(String productorName, MyBlockingQueue<Car> queue) {
			this.productorName = productorName;
			this.queue = queue;
		}

		@Override
		public void run() {
			Car car = new Car(productorName + ": car");
			queue.put(car);
			System.out.println("Productor: " + productorName + ", car: "
					+ car.getName());
		}
	}

	private static class Consumer implements Runnable {

		private String consumerName;
		private MyBlockingQueue<Car> queue;

		public Consumer(String consumerName, MyBlockingQueue<Car> queue) {
			this.consumerName = consumerName;
			this.queue = queue;
		}

		@Override
		public void run() {
			Car car = queue.take();
			System.out.println("Consumer: " + consumerName + ", car: "
					+ car.getName());
		}
	}

	private static class Car {
		private String name;

		public Car(String name) {
			this.name = name;
		}

		public String getName() {
			return name;
		}
	}

	private static class MyBlockingQueue<E> {
		private ReentrantLock lock = new ReentrantLock();
		private Condition notEmpty = lock.newCondition();
		private Condition notFull = lock.newCondition();

		private List<E> elements = new LinkedList<E>();
		private int capacity = 10;

		public MyBlockingQueue(int capacity) {
			if (capacity > 0 && capacity <= Integer.MAX_VALUE) {
				this.capacity = capacity;
			}
		}

		public void put(E e) {
			lock.lock();
			try {
				while (capacity == elements.size()) {
					try {
						notFull.await();
					} catch (InterruptedException e1) {
						e1.printStackTrace();
					}
				}
				elements.add(e);
				notEmpty.signalAll();
			} finally {
				lock.unlock();
			}
		}

		public E take() {
			lock.lock();
			try {
				while (elements.isEmpty()) {
					try {
						notEmpty.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				E e = elements.remove(0);
				notFull.signalAll();
				return e;
			} finally {
				lock.unlock();
			}
		}
	}
}

package com.my.study.concurrent;

import java.util.concurrent.CountDownLatch;

public class TestCountDownLatch {

	private static CountDownLatch countDownLatch = new CountDownLatch(3);

	public static void main(String[] args) {
		Runnable r1 = new SubClass("Sub1", 1000 * 1);
		Runnable r2 = new SubClass("Sub2", 1000 * 2);
		Runnable r3 = new SubClass("Sub3", 1000 * 3);
		new Thread(r1).start();
		new Thread(r2).start();
		new Thread(r3).start();

		System.out.println("All threads has been started.");

		try {
			countDownLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("CountDown finished.");
	}

	private static class SubClass implements Runnable {

		private String name;
		private long sleepTime;

		public SubClass(String name, long sleepTime) {
			this.name = name;
			this.sleepTime = sleepTime;
		}

		@Override
		public void run() {
			System.out.println(name + ", begin run()");
			try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(name + ", end run()");

			countDownLatch.countDown();
		}
	}
}

package com.my.study.concurrent;

import java.util.concurrent.CyclicBarrier;

public class TestCyclicBarrier {
	private static CyclicBarrier cyclicBarrier = new CyclicBarrier(3);

	public static void main(String[] args) {
		Runnable r1 = new SubClass("Sub1", 1000 * 1);
		Runnable r2 = new SubClass("Sub2", 1000 * 2);
		Runnable r3 = new SubClass("Sub3", 1000 * 3);
		new Thread(r1).start();
		new Thread(r2).start();
		new Thread(r3).start();

		System.out.println("All threads has been started.");
	}

	private static class SubClass implements Runnable {

		private String name;
		private long sleepTime;

		public SubClass(String name, long sleepTime) {
			this.name = name;
			this.sleepTime = sleepTime;
		}

		@Override
		public void run() {
			System.out.println(name + ", begin run()");
			try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			try {
				cyclicBarrier.await();
			} catch (Exception e) {
				e.printStackTrace();
			}

			System.out.println(name + ", end run()");
		}
	}
}

package com.my.study.concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class TestFutureTask {
	public static void main(String[] args) {

		Runnable r = new SubClass();
		String result = "This is result.";
		FutureTask<String> ft = new FutureTask<String>(r, result);
		new Thread(ft).start();
		try {
			String res = ft.get();
			System.out.println("Result is: " + res);
		} catch (Exception e) {
			e.printStackTrace();
		}

		// No need to get result.
		FutureTask<?> ft2 = new FutureTask<Void>(r, null);
		new Thread(ft2).start();
		try {
			ft2.get();
		} catch (Exception e) {
			e.printStackTrace();
		}

		Callable<String> c = new SubClass2();
		FutureTask<String> ft3 = new FutureTask<String>(c);
		new Thread(ft3).start();
		try {
			String res = ft3.get();
			System.out.println("Result is: " + res);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static class SubClass implements Runnable {

		@Override
		public void run() {
			System.out.println("Begin SubClass.run()");
			try {
				Thread.sleep(1000 * 3);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("End SubClass.run()");
		}
	}

	private static class SubClass2 implements Callable<String> {

		@Override
		public String call() throws Exception {
			System.out.println("Begin SubClass2.run()");
			try {
				Thread.sleep(1000 * 3);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("End SubClass2.run()");
			return "SubClass2.result";
		}

	}
}

package com.my.study.concurrent;

import java.util.concurrent.locks.ReentrantLock;

public class TestReentrantLock {
	public static void main(String[] args) {
		Runnable subClass = new SubClass();
		new Thread(subClass, "Thread1").start();
		new Thread(subClass, "Thread2").start();
	}

	private static class SubClass implements Runnable {

		private ReentrantLock lock = new ReentrantLock();

		@Override
		public void run() {
			prt();
		}

		private void prt() {
			lock.lock();
			try {
				System.out.println(Thread.currentThread().getName());
			} finally {
				lock.unlock();
			}
		}
	}
}


package com.my.study.concurrent;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReentrantReadWriteLock {

	public static void main(String[] args) {

		MyConcurrentHashMap<String, String> map = new MyConcurrentHashMap<String, String>();

		Runnable writeTask1 = new WriteTask(map, "key1", "value1");
		Runnable writeTask2 = new WriteTask(map, "key2", "value2");

		Runnable readTask1 = new ReadTask(map, "key1");
		Runnable readTask2 = new ReadTask(map, "key2");
		Runnable readTask3 = new ReadTask(map, "key3");

		new Thread(writeTask1).start();
		new Thread(writeTask2).start();
		new Thread(readTask1).start();

		new Thread(readTask2).start();
		new Thread(readTask3).start();
	}

	private static class ReadTask implements Runnable {

		private MyConcurrentHashMap<String, String> map;
		private String key;

		public ReadTask(MyConcurrentHashMap<String, String> map, String key) {
			this.map = map;
			this.key = key;
		}

		@Override
		public void run() {
			if (map == null) {
				System.out.println("map is null, cannot get value.");
				return;
			}

			String value = map.get(key);
			System.out.println("ReadTask, key is:" + key + ", value is:"
					+ value);
		}
	}

	private static class WriteTask implements Runnable {

		private MyConcurrentHashMap<String, String> map;
		private String key;
		private String value;

		public WriteTask(MyConcurrentHashMap<String, String> map, String key,
				String value) {
			this.map = map;
			this.key = key;
			this.value = value;
		}

		@Override
		public void run() {
			if (map == null) {
				System.out.println("map is null, cannot put value.");
				return;
			}

			map.put(key, value);

			System.out.println("WriteTask, key is:" + key + ", value is:"
					+ value);
		}
	}
}

class MyConcurrentHashMap<K, V> {
	private Map<K, V> map = new HashMap<K, V>();
	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private Lock readLock = lock.readLock();
	private Lock writeLock = lock.writeLock();

	public V put(K key, V value) {
		writeLock.lock();
		try {
			map.put(key, value);
			return value;
		} finally {
			writeLock.unlock();
		}
	}

	public V get(K key) {
		readLock.lock();
		try {
			return map.get(key);
		} finally {
			readLock.unlock();
		}
	}

	public boolean containsKey(K key) {
		readLock.lock();
		try {
			return map.containsKey(key);
		} finally {
			readLock.unlock();
		}
	}

	public V remove(K key) {
		writeLock.lock();
		try {
			return map.remove(key);
		} finally {
			writeLock.unlock();
		}
	}
}

package com.my.study.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;

public class TestSemaphore {

	private static Semaphore carSemaphore = new Semaphore(3);
	private static ExecutorService service = Executors.newFixedThreadPool(10);

	public static void main(String[] args) {
		List<Car> tasks = new ArrayList<Car>();
		for (int i = 0; i < 5; i++) {
			tasks.add(new Car("C" + i, carSemaphore));
		}
		try {
			List<Future<String>> futureList = service.invokeAll(tasks);
			for (Future<String> f : futureList) {
				System.out.println(f.get());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		service.shutdown();
	}

	private static class Car implements Callable<String> {

		private String name;

		private Semaphore semaphore;

		public Car(String name, Semaphore semaphore) {
			this.name = name;
			this.semaphore = semaphore;
		}

		@Override
		public String call() {
			park();
			try {
				Thread.sleep(1000 * 3);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			leave();
			return "OK, " + name;
		}

		private void park() {
			System.out.println("Trying to park, car: " + name);
			try {
				semaphore.acquire();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("Park done, car: " + name);
		}

		private void leave() {
			System.out.println("Trying to leave, car: " + name);
			semaphore.release();
			System.out.println("Leave done, car: " + name);
		}
	}
}

package com.my.study.concurrent;

public class TestSynchronized {

	public static void main(String[] args) {
		Runnable subClass = new SubClass();
		Thread t1 = new Thread(subClass, "Thread1");
		Thread t2 = new Thread(subClass, "Thread2");
		t1.start();

		try {
			Thread.sleep(1000 * 1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		t2.start();
	}

	private static class SubClass implements Runnable {

		@Override
		public void run() {
			prt();
		}

		private synchronized void prt() {
			System.out.println("Begin:" + Thread.currentThread().getName());

			try {
				Thread.sleep(1000 * 5);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println("End:" + Thread.currentThread().getName());
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值