当你使用synchronized关键字去保护一个代码块时,你必须传入一个对象的引用。

正常来讲,你讲使用this关键字去引用执行这个方法的对象,但是你可以使用其他对象的引用。

通常的,这些对象将会是专有的。例如,如果多个线程共享一个类中有2个独立的属性,你必须对每个变量做读取同步操作,

但是如果一个线程读取一个属性而另一个线程读取另一个这个没问题的。

本例中,你讲学会如何解决这个问题。我们将模拟带有2块屏幕和2个售票窗口的电影院。

当一个售票窗口买票时,它卖出的肯定是其中某个播放厅的座位,这样一来每个厅的座位数就是独立的属性。

Cinema.java
package com.dylan.thread.ch2.c02.task;

public class Cinema {

	/**
* This two variables store the vacancies in two cinemas
*/
private long vacanciesCinema1;
private long vacanciesCinema2; /**
* Two objects for the synchronization. ControlCinema1 synchronizes the
* access to the vacancesCinema1 attribute and controlCinema2 synchronizes
* the access to the vacanciesCinema2 attribute.
*/
private final Object controlCinema1, controlCinema2; /**
* Constructor of the class. Initializes the objects
*/
public Cinema(){
controlCinema1=new Object();
controlCinema2=new Object();
vacanciesCinema1=20;
vacanciesCinema2=20;
} /**
* This method implements the operation of sell tickets for the cinema 1
* @param number number of tickets sold
* @return true if the tickets are sold, false if there is no vacancies
*/
public boolean sellTickets1 (int number) {
synchronized (controlCinema1) {
if (number<vacanciesCinema1) {
vacanciesCinema1-=number;
return true;
} else {
return false;
}
}
} /**
* This method implements the operation of sell tickets for the cinema 2
* @param number number of tickets sold
* @return true if the tickets are sold, false if there is no vacancies
*/
public boolean sellTickets2 (int number){
synchronized (controlCinema2) {
if (number<vacanciesCinema2) {
vacanciesCinema2-=number;
return true;
} else {
return false;
}
}
} /**
* This method implements the operation of return tickets for the cinema 1
* @param number number of the tickets returned
* @return true
*/
public boolean returnTickets1 (int number) {
synchronized (controlCinema1) {
vacanciesCinema1+=number;
return true;
}
} /**
* This method implements the operation of return tickets for the cinema 1
* @param number number of the tickets returned
* @return true
*/
public boolean returnTickets2 (int number) {
synchronized (controlCinema2) {
vacanciesCinema2+=number;
return true;
}
} /**
* Return the vacancies in the cinema 1
* @return the vacancies in the cinema 1
*/
public long getVacanciesCinema1() {
return vacanciesCinema1;
} /**
* Return the vacancies in the cinema 2
* @return the vacancies in the cinema 2
*/
public long getVacanciesCinema2() {
return vacanciesCinema2;
} }

TicketOffice1.java
package com.dylan.thread.ch2.c02.task;

/**
* This class simulates a ticket office. It sell or return tickets
* for the two cinemas
*
*/
public class TicketOffice1 implements Runnable { /**
* The cinema
*/
private Cinema cinema; /**
* Constructor of the class
* @param cinema the cinema
*/
public TicketOffice1 (Cinema cinema) {
this.cinema=cinema;
} /**
* Core method of this ticket office. Simulates selling and returning tickets
*/
@Override
public void run() {
cinema.sellTickets1(3);
cinema.sellTickets1(2);
cinema.sellTickets2(2);
cinema.returnTickets1(3);
cinema.sellTickets1(5);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
} }
TicketOffice2
package com.dylan.thread.ch2.c02.task;

/**
* This class simulates a ticket office. It sell or return tickets
* for the two cinemas
*
*/
public class TicketOffice2 implements Runnable { /**
* The cinema
*/
private Cinema cinema; /**
* Constructor of the class
* @param cinema the cinema
*/
public TicketOffice2(Cinema cinema){
this.cinema=cinema;
} /**
* Core method of this ticket office. Simulates selling and returning tickets
*/
@Override
public void run() {
cinema.sellTickets2(2);
cinema.sellTickets2(4);
cinema.sellTickets1(2);
cinema.sellTickets1(1);
cinema.returnTickets2(2);
cinema.sellTickets1(3);
cinema.sellTickets2(2);
cinema.sellTickets1(2);
} }
Main.java
package com.dylan.thread.ch2.c02.core;

import com.dylan.thread.ch2.c02.task.Cinema;
import com.dylan.thread.ch2.c02.task.TicketOffice1;
import com.dylan.thread.ch2.c02.task.TicketOffice2; /**
* Core class of the example. Creates a cinema and two threads for
* the ticket office. Run the threads to analyze the results obtained
*
*/
public class Main { /**
* Main method of the example
* @param args
*/
public static void main(String[] args) {
// Creates a Cinema
Cinema cinema=new Cinema(); // Creates a TicketOffice1 and a Thread to run it
TicketOffice1 ticketOffice1=new TicketOffice1(cinema);
Thread thread1=new Thread(ticketOffice1,"TicketOffice1"); // Creates a TicketOffice2 and a Thread to run it
TicketOffice2 ticketOffice2=new TicketOffice2(cinema);
Thread thread2=new Thread(ticketOffice2,"TicketOffice2"); // Starts the threads
thread1.start();
thread2.start(); try {
// Waits for the finalization of the threads
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
} // Print the vacancies in the cinemas
System.out.printf("Room 1 Vacancies: %d\n",cinema.getVacanciesCinema1());
System.out.printf("Room 2 Vacancies: %d\n",cinema.getVacanciesCinema2());
} }

运行结果:

Room 1 Vacancies: 5
Room 2 Vacancies: 6

Java并发编程实例--14.在一个同步类中安排独立属性的更多相关文章

  1. Java并发编程:线程的同步

    Java并发编程:线程的同步 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...

  2. Java并发编程的4个同步辅助类

    Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...

  3. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)

    我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  4. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)

    我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  5. Java并发编程(三)Thread类的使用

    一.线程的状态 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time wait ...

  6. Java并发编程(六)-- 同步块

    上一节已经讲到,使用Synchronzied代码块可以解决共享对象的竞争问题,其实还有其他的方法也可以避免资源竞争问题,我统称他们为Java同步块.Java 同步块(synchronized bloc ...

  7. Java并发编程实例(synchronized)

    此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...

  8. Java并发编程(八)同步容器

    为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch) 一.为什么会出现同步容器? ...

  9. Java并发编程(二)同步

    在多线程的应用中,两个或者两个以上的线程需要共享对同一个数据的存取.如果两个线程存取相同的对象,并且每一个线程都调用了修改该对象的方法,这种情况通常成为竞争条件.  竞争条件最容易理解的例子就是:比如 ...

  10. [转]JAVA并发编程学习笔记之Unsafe类

    1.通过Unsafe类可以分配内存,可以释放内存:类中提供的3个本地方法allocateMemory.reallocateMemory.freeMemory分别用于分配内存,扩充内存和释放内存,与C语 ...

随机推荐

  1. [转帖]基于MySQL8.0存储过程实现myawr平台的top sql功能

    概述 众所周知,MySQL数据库中的performance_schema的事件统计表中的统计数据计算的是累计值,如果想要计算某段时间的TOP SQL是不行的,这里考虑用函数定期取值存进中间表定期将累计 ...

  2. [转帖]充分利用 Oracle SQL监控

    https://zhuanlan.zhihu.com/p/397834311 经常被问到查看执行计划的最佳工具是什么,对我来说,答案总是SQL Monitor(包含在 Oracle Tuning Pa ...

  3. [转帖]TiKV 多副本丢失以及修复实践

    https://tidb.net/blog/ad45bad9#6%E6%80%BB%E7%BB%93 1实验目的 随着tidb使用场景的越来越多,接入的业务越来越重要,不由得想试验下tidb组件的高可 ...

  4. [转帖]Linux—vi/vim批量注释及取消注释

    https://www.jianshu.com/p/45c252e9d2b6 应用场景   在开发场景中,经常遇到对一些配置文件进行注释,当然如果确定不用的时候我们可以通过vim中的D命令进行删除.当 ...

  5. [转帖]CentOS 7 下用 firewall-cmd / iptables 实现 NAT 转发供内网服务器联网

    https://www.cnblogs.com/hope250/p/8033818.html 自从用 HAProxy 对服务器做了负载均衡以后,感觉后端服务器真的没必要再配置并占用公网IP资源.而且由 ...

  6. .Net Core 3.1浏览器后端服务(二) Web API项目分层

    一.前言 分层开发的思想在计算机领域中至关重要,从操作系统到软件设计,分层思想无处不在. 在搭建项目的分层结构前,先简单了解下分层的优缺点.如下图,分为(呈现层.业务层.服务层.数据层) 分层的优点: ...

  7. 设置echarts线的样式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. TienChin 活动管理-工程创建

    工程模块的创建,与之前创建渠道管理一样的,所以这里就不贴图带着大家一起动手进行了,表结构我已经给到大家了,这里我只贴一下代码生成器的代码部分即可. @Test void generateActivit ...

  9. 华为云虚拟IP申请

    在上一篇文章当中我们搭建好了我们的 Nginx,这节呢,我们主要就是搭建我们的 Keepalive 与 Haproxy,搭建之前我们首先不要将我们华为云上面的弹性公网IP给取消了后续在取消,这次我介绍 ...

  10. GPTs prompts灵感库:创意无限,专业级创作指南,打造吸睛之作的秘诀

    GPTs prompts灵感库:创意无限,专业级创作指南,打造吸睛之作的秘诀 优质prompt展示 1.1 极简翻译 中英文转换 你是一个极简翻译工具,请在对话中遵循以下规则: - Prohibit ...