Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法
| 方法 | 特性 |
| synchronized | 不需要显式地加解锁,易实现 |
| ReentrantLock | 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 |
下文用三种不同的方式实现生产者/消费者模型
- synchronized结合wait/notify/notifyAll
- ReentrantLock结合Condition
- BlockingQueue(内部仍然采用ReentrantLock实现)
import java.util.Stack;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; /**
* @Description: 三种方法实现生产者/消费者
*/
public class ThreadSynchronizeTest { public static void main(String[] args) {
ProducerConsumer producerConsumer = new ProducerConsumerViaBlockingQueue();
producerConsumer.test();
}
} abstract class ProducerConsumer {
protected int capacity = 10;
protected int element = 0; protected abstract void produce() throws InterruptedException; protected abstract void consume() throws InterruptedException; public void test() {
Thread producer = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread consumer = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
producer.start();
consumer.start();
}
} /**
* 方法一:ReentrantLock结合Condition
*/
class ProducerConsumerViaReentrantLock extends ProducerConsumer {
private Stack<Integer> stack = new Stack<>();
private ReentrantLock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition(); @Override
protected void produce() throws InterruptedException {
try {
lock.lock();
if (stack.size() == capacity) {
notFull.await();
}
++element;
System.out.println(Thread.currentThread().getId() + " produce " + element);
stack.push(element);
notEmpty.signalAll();
} finally {
lock.unlock();
}
} @Override
protected void consume() throws InterruptedException {
try {
lock.lock();
if (stack.isEmpty()) {
notEmpty.await();
}
int element = stack.pop();
System.out.println(Thread.currentThread().getId() + " consume " + element);
notFull.signalAll();
} finally {
lock.unlock();
}
}
} /**
* 方法二:synchronized结合wait/notify/notifyAll
*/
class ProducerConsumerViaObjectLock extends ProducerConsumer {
private Stack<Integer> stack = new Stack<>();
private Object lock = new Object(); @Override
protected void produce() throws InterruptedException {
/**
* 1. lock为监视器<br/>
* 2. wait/notify/notifyAll方法必须在synchronized块内调用<br/>
* 3. 调用wait/notify/notifyAll方法但不持有监视器的使用权将会抛出java.lang.
* IllegalMonitorStateException<br/>
*/
synchronized (lock) {
if (stack.size() == capacity) {
lock.wait();
}
++element;
System.out.println(Thread.currentThread().getId() + " produce " + element);
stack.push(element);
lock.notifyAll();
}
} @Override
protected void consume() throws InterruptedException {
synchronized (lock) {
if (stack.isEmpty()) {
lock.wait();
}
int element = stack.pop();
System.out.println(Thread.currentThread().getId() + " consume " + element);
lock.notifyAll();
}
}
} /**
* 方法三:BlockingQueue
*/
class ProducerConsumerViaBlockingQueue extends ProducerConsumer {
private BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(capacity); @Override
protected void produce() throws InterruptedException {
++element;
System.out.println(Thread.currentThread().getId() + " produce " + element);
queue.put(element);
} @Override
protected void consume() throws InterruptedException {
int element = queue.take();
System.out.println(Thread.currentThread().getId() + " consume " + element);
}
}
Java多线程系列三——实现线程同步的方法的更多相关文章
- (Java多线程系列三)线程间通讯
Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...
- 【Java多线程系列三】实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式的加锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- java多线程(三)线程的安全问题
1.1. 什么是线程安全 如果有多个线程同时运行同一个实现了Runnable接口的类,程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的:反之,则是线程不 ...
- (Java多线程系列二)线程间同步
Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...
- java多线程系列六、线程池
一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池. 2. 使用线程池的好处 a) 降低资源的消耗.使用线程池不用频繁的创建线程和销毁线程 b) 提高响应速度,任 ...
- java多线程(2) 线程同步
我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步. 例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...
- java多线程系列7-停止线程
本文主要总结在java中停止线程的方法 在java中有以下三种方法可以终止正在运行的线程: 1.使用退出标志 2.使用stop方法强行终止线程,但是不推荐,因为stop和suspend.resume一 ...
- (Java多线程系列九)线程池
线程池 1.什么是线程池 线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程.线程池中线程的数量通常取决于可用内存数量和应用程序的需求. ...
随机推荐
- Python爬虫例子(笔记,不适合参考,愿意看的可以看看)
话不多说,直接上代码: import re import csv #爬虫的一个小例子,爬的是百度贴吧(网页版)某个帖子的各个楼层的用户名,发言内容和发言时间(使用到了正则表达式) source3.tx ...
- LeetCode(64) Minimum Path Sum
题目 Total Accepted: 47928 Total Submissions: 148011 Difficulty: Medium Given a m x n grid filled with ...
- Uva 1572 自组合
贴个源码// UVa1572 Self-Assembly // Rujia Liu #include<cstdio> #include<cstring> #include< ...
- 找到多个与名为“Home”的控制器匹配的类型。
原因分析 其实上面已经讲的很清楚了,找到了两个同名Home控制器,需要配置命名空间来区分. 解决方法 方法一:修改RouteConfig.cs 方法二:修改RouteConfig.cs 和 Admin ...
- Codeforces Round #259 (Div. 2) D
D. Little Pony and Harmony Chest time limit per test 4 seconds memory limit per test 256 megabytes i ...
- Django:(4)Django和Ajax
向服务器发送请求的途径: 1. 浏览器地址栏,默认get请求 2. form表单: get请求: post请求 3. a标签,默认get请求 4. Ajax:get请求:post请求 Ajax的特点( ...
- codevs 1378 选课
题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...
- Linux下汇编语言学习笔记0 --- 前期准备工作
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- IOS7状态栏StatusBar官方标准适配方法
IOS7状态栏StatusBar官方标准适配方法 hello,大家好,ios7正式版已经发布,相信大家都在以各种方式来适配ios7. 如果你已经下载了xcode5,正准备使用,你会发现各种布局的改变. ...
- Minimum Depth of Binary Tree(二叉树DFS)
Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...