两种实现线程同步的方法

方法 特性
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. flask编程规范

    参考:http://dormousehole.readthedocs.org/en/latest/styleguide.html   Flask遵循的是Pocoo的编程规范,Pocoo遵守PEP8的规 ...

  2. C++——模板

    1.参数类型 template <typename T> void f1(T&);//实参必须是左值 f1(i);//对 f1(ci);//对,T的类型是const int f1( ...

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

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

  4. 38-python基础-python3-检查字典中是否存在键或值

    in 和 not in 操作符   请注意, 在前面的例子中,‘name’ in spam 本质上是一个简写版本.相当于'name' in spam.keys()

  5. springboot Service层单元测试

    两个实现类实现同一个Service接口 public interface CustomUrlService { List<ShopMetrics> getShopMetrics(); } ...

  6. LeetCode Array Easy 167. Two Sum II - Input array is sorted

    Description Given an array of integers that is already sorted in ascending order, find two numbers s ...

  7. WiFi基础知识

    自从只需少量的话费就可以将笔记本.平板电脑连接到互联网,WiFi已成为我们熟知的网络,并无处不在.Wi-Fi对于一些物联网应用十分有用,比如楼宇自动化.内部能源管理.WiFi的重要性对于我们的日常生活 ...

  8. IT书单-持续更新

    重构:改善既有代码的设计代码整洁之道深入理解Java虚拟机Java并发编程的艺术<修改代码的艺术><程序员的职业素养>代码大全程序员修炼之道深入理解java虚拟机Java并发编 ...

  9. Windows虚拟机共享公司网络给Linux host

    前两天写了一个Linux主机通过windows虚拟机上网的随笔,实话说功能有点弱,比如22端口的转发都没有.实际上还有一个更简单且功能更强的共享方法(不需要安装ccproxy). https://ww ...

  10. JAVA企业级应用服务器之TOMCAT实战

    JAVA企业级应用服务器之TOMCAT实战 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App ...