Java 并发(JUC 包-01)

>JUC ? 就是Java API 中这三个包的简称:

>atomic 包

CAS:compare and swap ?要实现原子性操作

这是一种原子性操作,这是一种原子性赋值,

比如原来的 ++i ,现在对 i 进行原子性加一,从Java5之后就有了这个原子性操作,主要借助unsafe类(源码无法查看),Java为我们封装了一些类:

在atomic 包中

之前的例子改一下:

public class TestAtomic {
	V v = new V();

	public static void main(String[] args) {
		TestAtomic ta = new TestAtomic();
		ta.go();
	}

	private void go() {
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				public void run() {
					for (int j = 0; j < 10000; j++) {
						v.add();
					}
				}
			}).start();
		}
		while (Thread.activeCount() > 1) {

		}
		System.out.println(v.ai.get());
	}

	class V {
		//public int i = 0;
          public AtomicInteger ai=new AtomicInteger();
		public void add() {//原本在这个地方加个锁,将整个方法锁住了,悲观锁(重量级锁)
			//如果i++ 变成原子性的就没必要在外部加锁了
			//i++;
			ai.getAndIncrement();
		}
	}
}

>locks 包

1.重入锁基本使用:

public class TestLock {

	public static void main(String[] args) {
		new TestLock().go();
	}

	public void go() {
		V v = new V();
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					v.printString("AAAAAAAAAAAAAA");
				}
			}
		}).start();
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					v.printString("BBBBBBBBBBBBBB");
				}
			}
		}).start();
	}

	class V {
		// 使用Lock 代替 synchronized
		ReentrantLock lock = new ReentrantLock();

		public void printString(String str) {
			try {
				lock.lock();
				for (int i = 0; i < str.length(); i++) {
					System.out.print(str.charAt(i));
				}
				System.out.println();
			} catch (Exception e) {
			} finally {
				// 为了确保锁可以被释放掉
				lock.unlock();
			}

		}
	}
}

2.条件锁:使用条件锁实现线程轮询

public class TestConditionLock {
	V v = new V();

	public static void main(String[] args) {
		TestConditionLock t = new TestConditionLock();
		t.go();
	}

	private void go() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					v.f1();
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					v.f2();
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					v.f3();
				}
			}
		}).start();
	}

	class V {
		Lock lock = new ReentrantLock();
		Condition condition1 = lock.newCondition();
		Condition condition2 = lock.newCondition();
		Condition condition3 = lock.newCondition();
		int token = 1;

		public void f1() {
			lock.lock();
			try {
				while (token != 1) {
					try {
						condition1.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				token = 2;
				System.out.println(Thread.currentThread().getName() + "--f1");
				condition2.signal();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}

		public void f2() {
			lock.lock();
			try {
				while (token != 2) {
					try {
						condition2.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				token = 3;
				System.out.println(Thread.currentThread().getName() + "--f2");
				condition3.signal();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}

		public void f3() {
			lock.lock();
			try {
				while (token != 3) {
					try {
						condition3.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				token = 1;
				System.out.println(Thread.currentThread().getName() + "--f3");
				condition1.signal();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}
}

3.读写锁:

读写锁分为读锁和写锁。多个读锁之间不互斥、读锁和写锁之间互斥、写锁和写锁之间互斥。这一功能很重要,对并发读取提高了性能。

读写锁使用到了JUC中的ReentrantReadWriteLock类:

/**
 * 测试读写锁: 1.有个地方存东西 2.提供读和写两个方法,对这两个地方进行操作 3.开启多个线程,有读,有写 4.证明读的时候可以读,写的时候不能其他操作
 */
public class TestReentrantReadWriteLock {
	public static void main(String[] args) {
		TestReentrantReadWriteLock t = new TestReentrantReadWriteLock();
		t.go();
	}

	Data d = new Data();
	Random r = new Random();

	private void go() {
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					d.write(r.nextInt(1000));
				}
			}).start();
		}
		for (int i = 0; i < 5; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					d.read(r.nextInt(999));
				}
			}).start();
		}
	}

	class Data {
		List<Integer> list = new ArrayList<>();

		{
			for (int i = 0; i < 1000; i++) {
				list.add(i);
			}
		}

		// 创建读写锁
		ReadWriteLock lock = new ReentrantReadWriteLock();
		Lock readLock = lock.readLock();
		Lock writeLock = lock.writeLock();

		public void read(int index) {
			readLock.lock();
			try {
				System.out.println(Thread.currentThread().getName() + "进入读方法");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				int i = list.get(index);
				System.out.println(Thread.currentThread().getName() + "读到数据" + i);
				System.out.println(Thread.currentThread().getName() + "读取完毕");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				readLock.unlock();
			}
		}

		public void write(int data) {
			writeLock.lock();
			try {
				System.out.println(Thread.currentThread().getName() + "进入写方法");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				list.add(data);
				System.out.println(Thread.currentThread().getName() + "写入完毕");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				writeLock.unlock();
			}
		}
	}
}

显示:

Thread-0进入写方法
Thread-0写入完毕
Thread-1进入写方法
Thread-1写入完毕
Thread-2进入写方法
Thread-2写入完毕
Thread-3进入读方法
Thread-4进入读方法
Thread-5进入读方法
Thread-6进入读方法
Thread-7进入读方法
Thread-4读到数据403
Thread-5读到数据276
Thread-5读取完毕
Thread-7读到数据98
Thread-7读取完毕
Thread-6读到数据628
Thread-6读取完毕
Thread-3读到数据258
Thread-3读取完毕
Thread-4读取完毕

数据库中有表级别锁,行级锁,如何实现?思考。

单例模式中的同步代码块如何取代:

先看API实例:

class CachedData {
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     if (!cacheValid) {
        // Must release read lock before acquiring write lock
        rwl.readLock().unlock();
        rwl.writeLock().lock();
        try {
          // Recheck state because another thread might have
          // acquired write lock and changed state before we did.
          if (!cacheValid) {
            data = ...
            cacheValid = true;
          }
          // Downgrade by acquiring read lock before releasing write lock
          rwl.readLock().lock();
        } finally {
          rwl.writeLock().unlock(); // Unlock write, still hold read
        }
     }

     try {
       use(data);
     } finally {
       rwl.readLock().unlock();
     }
   }
 }

改造一下单例:

public class Book {
	private static Book instance = null;
	private static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

	public static Book getInstance() {
		try {
			rwl.readLock().lock();
			if (instance == null) {
				rwl.readLock().unlock();
				rwl.writeLock().lock();
				if (instance == null) {
					instance = new Book();
				}
				rwl.readLock().lock();
				rwl.writeLock().unlock();
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			rwl.readLock().unlock();
		}
		return instance;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章