两种实现线程同步的方法

方法 特性
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多线程系列三——实现线程同步的方法的更多相关文章

  1. (Java多线程系列三)线程间通讯

    Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...

  2. 【Java多线程系列三】实现线程同步的方法

    两种实现线程同步的方法 方法 特性 synchronized  不需要显式的加锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁  ...

  3. java多线程系列(三)---等待通知机制

    等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...

  4. java多线程(三)线程的安全问题

    1.1. 什么是线程安全 如果有多个线程同时运行同一个实现了Runnable接口的类,程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的:反之,则是线程不 ...

  5. (Java多线程系列二)线程间同步

    Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...

  6. java多线程系列六、线程池

    一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池. 2. 使用线程池的好处 a) 降低资源的消耗.使用线程池不用频繁的创建线程和销毁线程 b) 提高响应速度,任 ...

  7. java多线程(2) 线程同步

    我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步.   例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...

  8. java多线程系列7-停止线程

    本文主要总结在java中停止线程的方法 在java中有以下三种方法可以终止正在运行的线程: 1.使用退出标志 2.使用stop方法强行终止线程,但是不推荐,因为stop和suspend.resume一 ...

  9. (Java多线程系列九)线程池

    线程池 1.什么是线程池 线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程.线程池中线程的数量通常取决于可用内存数量和应用程序的需求. ...

随机推荐

  1. DataBase安装及简单配置

    下载以及安装 打开mysql官网下载页面:http://dev.mysql.com/downloads/mysql/ 用管理员身份打开cmd命令行工具,cd到解压文件的bin目录 输入mysqld i ...

  2. unity 菜单栏添加新菜单

    using UnityEngine; using System.Collections; using UnityEditor; public class jqmTools : CreateSphere ...

  3. xtu summer individual 3 F - Opening Portals

    Opening Portals Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

  4. Spring & Java

    Spring & Java https://spring.io/ Spring Boot https://www.shiyanlou.com/courses/1152 Spring Boot入 ...

  5. noip模拟赛 将军令

    分析:对于前18个点可以考虑非常恶心的树形dp,不推荐这种方法.其实贪心还是很显然的.每个小队可以控制距离不超过k里的驿站,肯定要让这个k里不能白白浪费.对于所有叶子节点,如果它还没有被控制,那么肯定 ...

  6. MVC Ajax.BeginForm重复提交解决方法

    mvc使用MVC Ajax.BeginForm提交的时候有重复提交结果的时候检查相关js文件引用情况, 其中mvc4注意 1 2 3 4 @Scripts.Render("~/bundles ...

  7. 仪仗队(bzoj 2190)

    Description 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是 ...

  8. 【IntelliJ】IntelliJ IDEA的安装破解及使用

    结合两位大牛CV的,写的很全面,仅供自己使用 转载地:http://www.jianshu.com/p/ad3830095fb3 https://www.cnblogs.com/kangjianwei ...

  9. Access restriction: The type 'JPEGImageWriter' is not API

    报错: Access restriction: The type 'JPEGImageWriter' is not API due to restriction on required library ...

  10. 使用NPOI将DataTable生成Excel

    听闻npoi 2.0版本支持excel2007格式了,表示期待其表现.不过目前还是使用1.2.5稳重点. 生活中有太多的列表都需要一个导出功能,当然这里的生活指的的程序员的生活.DataTable是从 ...