当前位置: 首页 > news >正文

多线程(二)

一、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
复制代码

相关文章:

  • [原]Java程序员的JavaScript学习笔记(4——闭包/getter/setter)
  • Dijkstra算法
  • 几种不错的编程字体
  • byte[]数组的正则表达式搜索 z
  • File类基本操作之OutputStream字节输出流
  • 全限定名
  • vsftpd基于pam_mysql的认证和hash编码的方式配置虚拟用户
  • Java中char转为16进制
  • 人脸识别算法初次了解
  • Python编程笔记(第三篇)【补充】三元运算、文件处理、检测文件编码、递归、斐波那契数列、名称空间、作用域、生成器...
  • Linux Memory Hotplug
  • 25个增强iOS应用程序性能的提示和技巧
  • 20165306 课下作业(第十周)
  • tortoise svn连接问题
  • 又一款基于BCH开发出来的社交软件BlockPress
  • CODING 缺陷管理功能正式开始公测
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • JavaScript设计模式系列一:工厂模式
  • JS+CSS实现数字滚动
  • k8s如何管理Pod
  • SpringCloud集成分布式事务LCN (一)
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • Vue全家桶实现一个Web App
  • webgl (原生)基础入门指南【一】
  • 今年的LC3大会没了?
  • 老板让我十分钟上手nx-admin
  • 离散点最小(凸)包围边界查找
  • 你真的知道 == 和 equals 的区别吗?
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  •  一套莫尔斯电报听写、翻译系统
  • 树莓派用上kodexplorer也能玩成私有网盘
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • (¥1011)-(一千零一拾一元整)输出
  • (1)bark-ml
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (蓝桥杯每日一题)love
  • (利用IDEA+Maven)定制属于自己的jar包
  • (六)Hibernate的二级缓存
  • (算法设计与分析)第一章算法概述-习题
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)scrum常见工具列表
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .CSS-hover 的解释
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET单元测试
  • .NET建议使用的大小写命名原则
  • .NET命令行(CLI)常用命令
  • .NET性能优化(文摘)
  • @Async注解的坑,小心