多线程(二)

一、ReentrantLock

1、重入锁

/**
 * ReentrantLock
 *  重入锁
 */
package concurrent.t03;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test_01 {
	Lock lock = new ReentrantLock();
	
	void m1(){
		try{
			lock.lock(); // 加锁
			for(int i = 0; i < 10; i++){
				TimeUnit.SECONDS.sleep(1);
				System.out.println("m1() method " + i);
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}finally{
			lock.unlock(); // 解锁
		}
	}
	
	void m2(){
		lock.lock();
		System.out.println("m2() method");
		lock.unlock();
	}
	
	public static void main(String[] args) {
		final Test_01 t = new Test_01();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.m1();
			}
		}).start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.m2();
			}
		}).start();
	}
}
复制代码

结果:

m1() method 0
m1() method 1
m1() method 2
m1() method 3
m1() method 4
m1() method 5
m1() method 6
m1() method 7
m1() method 8
m1() method 9
m2() method
复制代码

2、尝试锁

/**
 * 尝试锁
 */
package concurrent.t03;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test_02 {
	Lock lock = new ReentrantLock();
	
	void m1(){
		try{
			lock.lock();
			for(int i = 0; i < 10; i++){
				TimeUnit.SECONDS.sleep(1);
				System.out.println("m1() method " + i);
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	
	void m2(){
		boolean isLocked = false;
		try{
			// 尝试锁, 如果有锁,无法获取锁标记,返回false。
			// 如果获取锁标记,返回true
			// isLocked = lock.tryLock();
			
			// 阻塞尝试锁,阻塞参数代表的时长,尝试获取锁标记。
			// 如果超时,不等待。直接返回。
			isLocked = lock.tryLock(5, TimeUnit.SECONDS); 
			
			if(isLocked){
				System.out.println("m2() method synchronized");
			}else{
				System.out.println("m2() method unsynchronized");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(isLocked){
				// 尝试锁在解除锁标记的时候,一定要判断是否获取到锁标记。
				// 如果当前线程没有获取到锁标记,会抛出异常。
				lock.unlock();
			}
		}
	}
	
	public static void main(String[] args) {
		final Test_02 t = new Test_02();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.m1();
			}
		}).start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.m2();
			}
		}).start();
	}
}
复制代码

结果:

m1() method 0
m1() method 1
m1() method 2
m1() method 3
m1() method 4
m1() method 5
m2() method unsynchronized
m1() method 6
m1() method 7
m1() method 8
m1() method 9
复制代码

3、尝试打断(lockInterruptibly )

/**
 * 可打断
 * 
 * 阻塞状态: 包括普通阻塞,等待队列,锁池队列。
 * 普通阻塞: sleep(10000), 可以被打断。调用thread.interrupt()方法,可以打断阻塞状态,抛出异常。
 * 等待队列: wait()方法被调用,也是一种阻塞状态,只能由notify唤醒。无法打断
 * 锁池队列: 无法获取锁标记。不是所有的锁池队列都可被打断。
 *  使用ReentrantLock的lock方法,获取锁标记的时候,如果需要阻塞等待锁标记,无法被打断。
 *  使用ReentrantLock的lockInterruptibly方法,获取锁标记的时候,如果需要阻塞等待,可以被打断。
 * 
 */
package concurrent.t03;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test_03 {
	Lock lock = new ReentrantLock();
	
	void m1(){
		try{
			lock.lock();
			for(int i = 0; i < 5; i++){
				TimeUnit.SECONDS.sleep(1);
				System.out.println("m1() method " + i);
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	
	void m2(){
		try{
			lock.lockInterruptibly(); // 可尝试打断,阻塞等待锁。可以被其他的线程打断阻塞状态
			System.out.println("m2() method");
		}catch(InterruptedException e){
			System.out.println("m2() method interrupted");
		}finally{
			try{
				lock.unlock();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		final Test_03 t = new Test_03();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.m1();
			}
		}).start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				t.m2();
			}
		});
		t2.start();
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t2.interrupt();// 打断线程休眠。非正常结束阻塞状态的线程,都会抛出异常。
	}
}
复制代码

结果:

m1() method 0
m1() method 1
m2() method interrupted
java.lang.IllegalMonitorStateException
	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
	at java.util.concurrent.locks.ReentrantLock.unlock(Unknown Source)
	at concurrent.t03.Test_03.m2(Test_03.java:43)
	at concurrent.t03.Test_03$2.run(Test_03.java:67)
	at java.lang.Thread.run(Unknown Source)
m1() method 2
m1() method 3
m1() method 4
复制代码

4、公平锁

/**
 * 公平锁
 */
package concurrent.t03;

import java.util.concurrent.locks.ReentrantLock;

public class Test_04 {
	
	public static void main(String[] args) {
		TestReentrantlock t = new TestReentrantlock();
		//TestSync t = new TestSync();
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t1.start();
		t2.start();
	}
}

class TestReentrantlock extends Thread{
	// 定义一个公平锁
	private static ReentrantLock lock = new ReentrantLock(true);
	public void run(){
		for(int i = 0; i < 5; i++){
			lock.lock();
			try{
				System.out.println(Thread.currentThread().getName() + " get lock");
			}finally{
				lock.unlock();
			}
		}
	}
	
}

class TestSync extends Thread{
	public void run(){
		for(int i = 0; i < 5; i++){
			synchronized (this) {
				System.out.println(Thread.currentThread().getName() + " get lock in TestSync");
			}
		}
	}
}
复制代码

结果:

Thread-2 get lock
Thread-1 get lock
Thread-2 get lock
Thread-1 get lock
Thread-2 get lock
Thread-1 get lock
Thread-2 get lock
Thread-1 get lock
Thread-2 get lock
Thread-1 get lock
复制代码

二、生产者消费者

1)、wait&notify

/**
 * 生产者消费者
 * wait&notify
 * wait/notify都是和while配合应用的。可以避免多线程并发判断逻辑失效问题。
 */
package concurrent.t04;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class TestContainer01<E> {

	private final LinkedList<E> list = new LinkedList<>();
	private final int MAX = 10;
	private int count = 0;
	
	public synchronized int getCount(){
		return count;
	}
	
	public synchronized void put(E e){
		while(list.size() == MAX){
			try {
				this.wait();
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		}
		
		list.add(e);
		count++;
		this.notifyAll();
	}
	
	public synchronized E get(){
		E e = null;
		while(list.size() == 0){
			try{
				this.wait();
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		}
		e = list.removeFirst();
		count--;
		this.notifyAll();
		return e;
	}
	
	public static void main(String[] args) {
		final TestContainer01<String> c = new TestContainer01<>();
		for(int i = 0; i < 10; i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					for(int j = 0; j < 5; j++){
						System.out.println(c.get());
					}
				}
			}, "consumer"+i).start();
		}
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for(int i = 0; i < 2; i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					for(int j = 0; j < 25; j++){
						c.put("container value " + j); 
					}
				}
			}, "producer"+i).start();
		}
	}
	
}
复制代码

结果:

container value 0
container value 5
container value 6
container value 5
container value 6
container value 4
container value 1
container value 3
container value 2
container value 1
container value 0
container value 4
container value 2
container value 3
复制代码

2)、重入锁&条件

/**
 * 生产者消费者
 * 重入锁&条件
 * 条件 - Condition, 为Lock增加条件。当条件满足时,做什么事情,如加锁或解锁。如等待或唤醒
 */
package concurrent.t04;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestContainer02<E> {

	private final LinkedList<E> list = new LinkedList<>();
	private final int MAX = 10;
	private int count = 0;
	
	private Lock lock = new ReentrantLock();
	private Condition producer = lock.newCondition();
	private Condition consumer = lock.newCondition();
	
	public int getCount(){
		return count;
	}
	
	public void put(E e){
		lock.lock();
		try {
			while(list.size() == MAX){
				System.out.println(Thread.currentThread().getName() + " 等待。。。");
				// 进入等待队列。释放锁标记。
				// 借助条件,进入的等待队列。
				producer.await();
			}
			System.out.println(Thread.currentThread().getName() + " put 。。。");
			list.add(e);
			count++;
			// 借助条件,唤醒所有的消费者。
			consumer.signalAll();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public E get(){
		E e = null;

		lock.lock();
		try {
			while(list.size() == 0){
				System.out.println(Thread.currentThread().getName() + " 等待。。。");
				// 借助条件,消费者进入等待队列
				consumer.await();
			}
			System.out.println(Thread.currentThread().getName() + " get 。。。");
			e = list.removeFirst();
			count--;
			// 借助条件,唤醒所有的生产者
			producer.signalAll();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} finally {
			lock.unlock();
		}
		
		return e;
	}
	
	public static void main(String[] args) {
		final TestContainer02<String> c = new TestContainer02<>();
		for(int i = 0; i < 10; i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					for(int j = 0; j < 5; j++){
						System.out.println(c.get());
					}
				}
			}, "consumer"+i).start();
		}
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		for(int i = 0; i < 2; i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					for(int j = 0; j < 25; j++){
						c.put("container value " + j); 
					}
				}
			}, "producer"+i).start();
		}
	}
	
}
复制代码

结果:

consumer0 等待。。。
consumer1 等待。。。
consumer2 等待。。。
consumer3 等待。。。
consumer6 等待。。。
consumer5 等待。。。
consumer9 等待。。。
consumer8 等待。。。
consumer4 等待。。。
consumer7 等待。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 等待。。。
producer1 等待。。。
consumer0 get 。。。
container value 0
consumer0 get 。。。
container value 1
consumer0 get 。。。
container value 2
consumer0 get 。。。
container value 3
consumer1 get 。。。
container value 4
consumer1 get 。。。
container value 5
consumer2 get 。。。
container value 6
consumer3 get 。。。
container value 7
consumer3 get 。。。
container value 8
consumer6 get 。。。
container value 9
consumer6 等待。。。
consumer5 等待。。。
consumer9 等待。。。
consumer8 等待。。。
consumer4 等待。。。
consumer7 等待。。。
producer0 put 。。。
producer0 put 。。。
producer1 put 。。。
producer1 put 。。。
consumer0 get 。。。
container value 10
consumer1 get 。。。
container value 11
consumer1 get 。。。
container value 0
consumer1 get 。。。
container value 1
consumer2 等待。。。
consumer3 等待。。。
consumer6 等待。。。
consumer5 等待。。。
consumer9 等待。。。
consumer8 等待。。。
consumer4 等待。。。
consumer7 等待。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 put 。。。
producer0 等待。。。
producer1 等待。。。
consumer2 get 。。。
container value 12
consumer2 get 。。。
container value 13
consumer2 get 。。。
container value 14
consumer2 get 。。。
container value 15
consumer3 get 。。。
container value 16
consumer6 get 。。。
container value 17
consumer6 get 。。。
container value 18
consumer5 get 。。。
container value 19
consumer9 get 。。。
container value 20
consumer9 get 。。。
container value 21
consumer8 等待。。。
consumer4 等待。。。
consumer7 等待。。。
producer0 put 。。。
producer0 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 等待。。。
consumer3 get 。。。
container value 22
consumer6 get 。。。
container value 23
consumer5 get 。。。
container value 2
consumer5 get 。。。
container value 3
consumer5 get 。。。
container value 4
consumer5 get 。。。
container value 5
consumer9 get 。。。
container value 6
consumer8 get 。。。
container value 7
consumer4 get 。。。
container value 8
consumer4 get 。。。
container value 9
consumer7 等待。。。
producer0 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 等待。。。
consumer3 get 。。。
container value 24
consumer6 get 。。。
container value 10
consumer9 get 。。。
container value 11
consumer8 get 。。。
container value 12
consumer8 get 。。。
container value 13
consumer8 get 。。。
container value 14
consumer8 get 。。。
container value 15
consumer4 get 。。。
container value 16
consumer7 get 。。。
container value 17
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
producer1 put 。。。
consumer9 get 。。。
container value 18
consumer4 get 。。。
container value 19
consumer7 get 。。。
container value 20
consumer7 get 。。。
container value 21
consumer7 get 。。。
container value 22
consumer7 get 。。。
container value 23
consumer4 get 。。。
container value 24
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值