目录
一、线程通信使用synchronized实现
案例:使用两个线程,实现对一个初始值是0的变量操作,一个线程对其进行加一操作,另一个线程对其进行减一操作,这个过程就是线程通信。
三步骤:判断、干活、通知
参考示例代码:
public class ThreadDemo01 {
public static void main(String[] args) {
//创建对象
Share share = new Share();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"aa").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"bb").start();
}
}
/**
* 创建资源类
*/
class Share{
private int number = 0;
//加的方法
public synchronized void incr() throws InterruptedException {
//判断number是否为零,不是零就等待
if (number != 0){
this.wait();
}
//不为零就加一
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
}
//减的方法
public synchronized void decr() throws InterruptedException {
//判断number是否为一,不是一就等待
if (number != 1){
this.wait();
}
//不为零就加一
number--;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
}
}
上面的代码存在虚假唤醒
示例代码:
public class ThreadDemo01 {
public static void main(String[] args) {
//创建对象
Share share = new Share();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"aa").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"bb").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"cc").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"dd").start();
}
}
/**
* 创建资源类
*/
class Share{
private int number = 0;
//加的方法
public synchronized void incr() throws InterruptedException {
//判断number是否为零,不是零就等待
if (number != 0){
this.wait();
}
//不为零就加一
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
}
//减的方法
public synchronized void decr() throws InterruptedException {
//判断number是否为一,不是一就等待
if (number != 1){
this.wait();
}
//不为零就加一
number--;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
}
}
运行结果:
原因是wait方法引起的:
由于wait方法的特点就是在那里睡就在那里醒,会导致if判断条件失效。
解决方法将if判断修改为while循环
参考示例代码:
public class ThreadDemo01 {
public static void main(String[] args) {
//创建对象
Share share = new Share();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"aa").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"bb").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"cc").start();
//创建线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"dd").start();
}
}
/**
* 创建资源类
*/
class Share{
private int number = 0;
//加的方法
public synchronized void incr() throws InterruptedException {
//判断number是否为零,不是零就等待
while (number != 0){
this.wait();
}
//不为零就加一
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
}
//减的方法
public synchronized void decr() throws InterruptedException {
//判断number是否为一,不是一就等待
while (number != 1){
this.wait();
}
//不为零就加一
number--;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
}
}
正确运行结果:
二、基于lock接口实现
public class ThreadDemo2 {
public static void main(String[] args) {
Share share = new Share();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"aa").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"bb").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"cc").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"dd").start();
}
}
class Share{
private int number = 0;
//创建lock对象
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
//加
public void incr() throws InterruptedException {
//上锁
lock.lock();
try {
while (number != 0){
condition.await();
}
//加一
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
condition.signalAll();
}finally {
//解锁
lock.unlock();
}
}
//减
public void decr() throws InterruptedException {
//上锁
lock.lock();
try {
while (number != 1){
condition.await();
}
//加一
number--;
System.out.println(Thread.currentThread().getName()+"::"+number);
condition.signalAll();
}finally {
//解锁
lock.unlock();
}
}
}