两种实现线程同步的方法

方法 特性
synchronized  不需要显式的加锁,易实现
ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 
package com.concurrent.test;

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() + "," + Thread.currentThread().getName() + " produce " + element);
stack.push(element);
notEmpty.signalAll();
Thread.sleep(1000L);
} 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() + "," + Thread.currentThread().getName() + " 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为监视器
* 2,wait/notify/notifyAll方法必须在synchronized块内调用
* 3,调用wait/notify/notifyAll方法但不持有监视器的使用权将会抛出java.lang.IllegalMonitorStateException
*/
synchronized (lock) {
if (stack.size() == capacity) {
lock.wait();
} ++element;
System.out.println(Thread.currentThread().getId() + "," + Thread.currentThread().getName() + " produce " + element);
stack.push(element);
lock.notifyAll();
Thread.sleep(1000L);
}
} @Override
protected void consume() throws InterruptedException {
synchronized (lock) {
if (stack.isEmpty()) {
lock.wait();
} int element = stack.pop();
System.out.println(Thread.currentThread().getId() + "," + Thread.currentThread().getName() + " 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() + "," + Thread.currentThread().getName() + " produce " + element);
queue.put(element);
Thread.sleep(1000L);
} @Override
protected void consume() throws InterruptedException {
int element = queue.take();
System.out.println(Thread.currentThread().getId() + " consume " + element);
Thread.sleep(10000L);
}
}

【Java多线程系列三】实现线程同步的方法的更多相关文章

  1. Java多线程系列三——实现线程同步的方法

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

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

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

  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. JQuery Mobile 图片布局

    JQuery Mobile 图片布局 1.实现效果

  2. Java第四次作业—面向对象高级特性(继承和多态)

    Java第四次作业-面向对象高级特性(继承和多态) (一)学习总结 1.学习使用思维导图对Java面向对象编程的知识点(封装.继承和多态)进行总结. 2.阅读下面程序,分析是否能编译通过?如果不能,说 ...

  3. spss乱码问题解决

    spss乱码问题解决 方法1:网友kuangsir6提供 选择字体为:DFKai-SB 格式(我并没有找到这个格式) 方法是 SPSS(PASW)---Edit---Options---Viewer- ...

  4. 运维 07 Linux系统基础优化及常用命令

    Linux系统基础优化及常用命令   Linux基础系统优化 引言没有,只有一张图. Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令 ...

  5. 一个线上Java空指针问题的排查经过

    某天,运营反馈,某商品下单异常 1.原来是一个空指针报错 根据用户输入的下单关键信息搜索日志系统看到如下报错 stackTrace: "java.lang.NullPointerExcept ...

  6. JS的常用正则表达式 验证密码用户名等

    //校验是否全由数字组成 function isDigit(s) { var patrn=/^[0-9]{1,20}$/; if (!patrn.exec(s)) return false retur ...

  7. CF_127E reader Display

    这道题其实找到规律之后其实不难,和破损的键盘一样,都有点递推转移的感觉 题意: 你可以进行这样一次操作:选一个点,然后把这个点横切竖切直到正对角线上面的点,全部翻转过来,问你要进行多少次操作才能把所有 ...

  8. windows下虚拟环境的安装与创建

    使用虚拟环境的好处: 可以方便的解决不同项目对类库的依赖问题. 可以在系统中Python解释器中避免包的混乱和版本的冲突. 为每个程序单独创建虚拟环境,可以保证程序只能访问虚拟环境中的包,保持全局解释 ...

  9. 关于Oracle中Sort Merge Join的改写

    业务场景的问题,我们有一个刷CUBE的SQL,是Oracle环境,平时跑70多分钟, 但是最近突然不动了,这个SQL需要算累计值,比如年累计客户数量. 累计值是什么意思呢?我们使用下面的数据来说明问题 ...

  10. Sed的查,删,增,改

    sed的查,删,增,改 1.sed的查找 2.sed的删除 3.sed的上下左右增加文件内容 4.sed的改