并发编程系列小结(线程安全,synchronized,脏读,线程间的通信wait/notify,线程的三种实现方式Demo,可替代wait/notify的方法)
线程安全:
当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法就是线程安全的)
synchronized:
可以在任意对象或方法上加锁,而加锁的这段代码称为“互斥区”或“临界区”
多个线程多个锁:
多个线程都有自己对应的锁
脏读:
在我们对一个对象的方法或对象加锁时,需要考虑业务的整体性,即为setValue/getValue方法同时加锁synchronized同步关键字,保证业务的原子性,不然会出现业务错误(也从侧面保证了数据的一致性)
线程间的通信:
使用notify/wait方法实现线程间的通信(注意这两个方法都是object类的方法)
wait/ notify 必须配合synchronized关键字使用
wait方法释放锁,notify方法不释放锁
CountDownLatch与锁无关
线程的三种实现方式Demo
package com.jonychen.test; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; /**
* 线程的三种实现方式
*/
public class TestDemo { public static void main(String[] args){
/**
* 第一种方式:继承Thread类重写run()方法
*/
Thread thread=new ThreadDemo();
thread.start(); /**
* 第二种方式:实现Runnable接口重写run()方法
*/
RunnableDemo runnableDemo=new RunnableDemo();
Thread thread1=new Thread(runnableDemo);
thread1.start();
try {
thread1.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} /**
* 第三种方式:实现Callable接口重写call()方法
*/
CallableDemo callableDemo =new CallableDemo();
FutureTask<Integer> futureTask=new FutureTask<Integer>(callableDemo);
Thread thread2=new Thread(futureTask);
thread2.start();
try {
System.out.println("返回的参数为:"+futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
} /**
* 第一种方式:继承Thread类重写run()方法
*/
class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("我是继承Thread类实现线程的一种方式!");
}
} /**
* 第二种方式:实现Runnable接口重写run()方法
*/
class RunnableDemo implements Runnable{
@Override
public void run() {
System.out.println("我是实现Runnable接口实现线程的一种方式");
}
} /**
* 第三种方式:实现Callable接口重写call()方法
*/
class CallableDemo implements Callable<Integer>{ @Override
public Integer call(){
return 666666;
}
}
输出截图:

可替代wait/notify的方法
package com.jonychen.test; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
*java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,
* 其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。
* 相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。
*
* 使用 Lock 来获取一个 Condition 对象。
*/
public class ConcurrentDemo { private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition(); public void before(){
lock.lock();
try {
System.out.println("before");
condition.signalAll();
} finally {
lock.unlock();
}
} public void after(){
lock.lock();
try {
condition.await();
System.out.println("after");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
} } public static void main(String[] args){ ExecutorService executorService =Executors.newCachedThreadPool();
ConcurrentDemo concurrentDemo=new ConcurrentDemo();
executorService.execute(()->concurrentDemo.after());
executorService.execute(()->concurrentDemo.before());
} }
并发编程系列小结(线程安全,synchronized,脏读,线程间的通信wait/notify,线程的三种实现方式Demo,可替代wait/notify的方法)的更多相关文章
- python并发编程之多进程1-----------互斥锁与进程间的通信
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python并发编程之多进程1--(互斥锁与进程间的通信)
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python并发编程之多进程1互斥锁与进程间的通信
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- java并发编程系列原理篇--JDK中的通信工具类Semaphore
前言 java多线程之间进行通信时,JDK主要提供了以下几种通信工具类.主要有Semaphore.CountDownLatch.CyclicBarrier.exchanger.Phaser这几个通讯类 ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- Java并发编程系列-(7) Java线程安全
7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...
- 原创】Java并发编程系列2:线程概念与基础操作
[原创]Java并发编程系列2:线程概念与基础操作 伟大的理想只有经过忘我的斗争和牺牲才能胜利实现. 本篇为[Dali王的技术博客]Java并发编程系列第二篇,讲讲有关线程的那些事儿.主要内容是如下这 ...
- Java并发编程系列-(2) 线程的并发工具类
2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...
- Java并发编程系列-(6) Java线程池
6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...
随机推荐
- EL表达式无法显示Model中的数据
后台程序通过Debug都能正常返回数据并封装到Model中.而在前台通过EL表达式取值时却是原样输出,如${cart.num}... ///展现我的购物车 @RequestMapping(" ...
- 对TDD原则的理解
1,在编写好失败的单元测试之前,不要编写任何产品代码 如果不先写测试,那么各个函数就会耦合在一起,最后变得无法测试 如果后写测试,你也许能对大块大块的代码进行测试,但是无法对每个函数进行测 ...
- Struts2 简单的上传文件并且显示图片
代码结构: UploadAction.java package com.action; import java.io.File; import java.io.FileInputStream; imp ...
- Poj1182 食物链(并查集/带权并查集)
题面 Poj 题解 这里采用并查集的补集. \(x\)表示同类集合,\(x+n\)表示敌人集合,\(x+n\times2\)表示敌人的敌人集合. 如果当前给出的是一对同类关系,就判断\(x\)是否吃\ ...
- 洛谷——P2082 区间覆盖(加强版)
P2082 区间覆盖(加强版) 题目描述 已知有N个区间,每个区间的范围是[si,ti],请求出区间覆盖后的总长. 输入输出格式 输入格式: N s1 t1 s2 t2 …… sn tn 输出格式: ...
- SCU - 4441 Necklace(树状数组求最长上升子数列)
Necklace frog has \(n\) gems arranged in a cycle, whose beautifulness are \(a_1, a_2, \dots, a_n\). ...
- Struts2与Servlet之间的关系
在struts2.0中,可以通过ServletActionContext.getRequest()获取request对象. 在action的方法中return一个字符串,该字符串对应struts.xm ...
- [P2526][SHOI2001]小狗散步
Link: P2526 传送门 Solution: 一道提示非常到位的题目 题面中强调了在两个路径相邻点间只能再去至多一个点,且每个点只计算一次贡献 于是明显可以将原题看作询问在两个不相交点集间最多能 ...
- ZOJ 2589 Circles(平面图欧拉公式)
[题目链接] http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2589 [题目大意] 给出一些圆,问这些圆可以把平面分为几个部 ...
- 【随机化】Petrozavodsk Summer Training Camp 2016 Day 5: Petr Mitrichev Contest 14, Saturday, August 27, 2016 Problem I. Vier
给你一个1~n的排列,让你找出4个下标a b c d,满足 (a+b)%n=(c+d)%n (w(a)+w(b))%n=(w(c)+w(d))%n,并且是非平凡解. 发现对于每个数i,找出两个数和为其 ...