线程同步的实现方式(volatile、synchronized、CountDownLatch)
题目:
自定义容器,提供新增元素(add)和获取元素数量(size)方法。启动两个线程。
线程1向容器中新增10个数据。线程2监听容器元素数量,当容器元素数量为5时,线程2输出信息并终止。
方法一:volatile
/**
* volatile
*/import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit; public class Test_01 {
public static void main(String[] args) {
final Test_01_Container t = new Test_01_Container();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("add Object to Container " + i);
t.add(new Object());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (t.size() == 5) {
System.out.println("size = 5");
break;
}
}
}
}).start();
}
} class Test_01_Container {
volatile List<Object> container = new ArrayList<>(); public void add(Object o) {
this.container.add(o);
} public int size() {
return this.container.size();
}
}
方法二:synchronized
/**
* wait notify
*/
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit; public class Test_02 {
public static void main(String[] args) {
final Test_02_Container t = new Test_02_Container();
final Object lock = new Object(); new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
if (t.size() != 5) {
try {
lock.wait(); // 线程进入等待队列。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("size = 5");
lock.notifyAll(); // 唤醒其他等待线程
}
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
System.out.println("add Object to Container " + i);
t.add(new Object());
if (t.size() == 5) {
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
} class Test_02_Container {
List<Object> container = new ArrayList<>(); public void add(Object o) {
this.container.add(o);
} public int size() {
return this.container.size();
}
}
方法三:CountDownLatch
/**
* CountDownLatch 门闩
*/
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; public class Test_03 {
public static void main(String[] args) {
final Test_03_Container t = new Test_03_Container();
final CountDownLatch latch = new CountDownLatch(1); new Thread(new Runnable() {
@Override
public void run() {
if (t.size() != 5) {
try {
latch.await(); // 等待门闩的开放。 不是进入等待队列
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("size = 5");
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("add Object to Container " + i);
t.add(new Object());
if (t.size() == 5) {
latch.countDown(); // 门闩-1
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
} class Test_03_Container {
List<Object> container = new ArrayList<>(); public void add(Object o) {
this.container.add(o);
} public int size() {
return this.container.size();
}
}
线程同步的实现方式(volatile、synchronized、CountDownLatch)的更多相关文章
- C# 线程同步的多种方式
实际应用中多个线程往往需要共享数据,因此必须使用同步技术,确保一次只有一个线程访问和改变共享数据.同步又分为进程内部线程的同步以及进程之间线程的同步. 进程内部线程同步: 1. lock : 使用比较 ...
- java笔记--关于线程同步(7种同步方式)
关于线程同步(7种方式) --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3897440.html"谢谢-- 为何要使用同步? ...
- 线程同步(使用了synchronized)和线程通讯(使用了wait,notify)
线程同步 什么是线程同步? 当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题. 实现同步机制有两个方法:1.同 ...
- java线程同步以及对象锁和类锁解析(多线程synchronized关键字)
一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...
- (删)Java线程同步实现二:Lock锁和Condition
在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...
- Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- Java中处理线程同步
引自:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8295527和http://m.blog.csdn.net/blog/undoner/1 ...
- Java多线程与并发库高级应用-传统线程同步通信技术
面试题: 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着又 主线程循环100次,如此循环50次,请写出程序 /** * 子线程循环10次,接着主线程循环100次,接着又回到 ...
- C#线程同步技术(二) Interlocked 类
接昨天谈及的线程同步问题,今天介绍一个比较简单的类,Interlocked.它提供了以线程安全的方式递增.递减.交换和读取值的方法. 它的特点是: 1.相对于其他线程同步技术,速度会快很多. 2.只能 ...
随机推荐
- MyBatis中使用#和$书写占位符有什么区别?
#将传入的数据都当成一个字符串,会对传入的数据自动加上引号:$将传入的数据直接显示生成在SQL中.注意:使用$占位符可能会导致SQL注射攻击,能用#的地方就不要使用$,写order by子句的时候应该 ...
- Linux内核中的printf实现
1 #ifndef __PRINT_H_ 2 #define __PRINT_H_ 3 4 void print(char* fmt, ...); 5 void printch(char ch); 6 ...
- 用 Python 获取 B 站播放历史记录
用 Python 获取 B 站播放历史记录 最近 B 站出了一个年度报告,统计用户一年当中在 B 站上观看视频的总时长和总个数.过去一年我居然在 B 站上看了2600+个视频,总计251个小时,居然花 ...
- 【学习】数据规整化:清理、转换、合并、重塑【pandas】
这一部分非常关键! 数据分析和建模方面的大量编程工作都是用在数据准备上的:加载.清理.转换以及重塑. 1.合并数据集 pandas对象中的数据可以通过 一些内置的方式进行合并: pandas.merg ...
- maven dependency的版本冲突问题
在改造一个旧项目中,遇到各种问题. 旧项目有十多个模块,因为没有一个统一的父pom,它们对第三方的jar的版本没有统一. 虽然也存在公共的依赖模块,比如commons.util,但是,我们的模块中,有 ...
- 彻底搞懂Scrapy的中间件(三)
在前面两篇文章介绍了下载器中间件的使用,这篇文章将会介绍爬虫中间件(Spider Middleware)的使用. 爬虫中间件 爬虫中间件的用法与下载器中间件非常相似,只是它们的作用对象不同.下载器中间 ...
- pgadmin连接 postgresql远程设置
背景:通过yum默认方式将pgsql10安装在centos7, pgsql 的配置文件在:/var/lib/pgsql/10/data. 配置文件:postgresql.conf 和 pg_hba.c ...
- HTTP请求头与响应头(转载)
欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/400503 ...
- v-for key
key 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略.如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素 ...
- 吴裕雄 python 机器学习——ElasticNet回归
import numpy as np import matplotlib.pyplot as plt from matplotlib import cm from mpl_toolkits.mplot ...