当你使用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. [转帖]Java 8 要过时了?从JDK8飞升到JDK17,一次性给你讲明白

    https://blog.csdn.net/agonie201218/article/details/127916729?spm=1001.2101.3001.6650.2&utm_mediu ...

  2. [转帖]elasticsearch8.0以上版本修改内置用户密码

    https://www.cnblogs.com/zhang-ding-1314/p/16199682.html 修改密码需要在es启动,并cd到es的bin目录下执行: 1.重置密码并在控制台显示新密 ...

  3. Python学习之十九_程序运行时间的验证

    Python学习之十九_程序运行时间的验证 背景 最近一段时间比较忙. 而且还遇到了一个lua脚本优化redis访问的场景. 想着自己还在学习python(时断时续) 所以想借着这个场景,学习一下py ...

  4. [转帖]总结:Servlet

    一.背景 开发了很久的web服务,使用了很多web框架,都忘记web技术最原始的模样了,今天来回顾下. 二.Servlet是什么? Servlet是sun公司提供的一门用于开发动态web资源的技术.我 ...

  5. sringboot 调试端口启用的写法

    注意 需要在 -jar 的后面加 加在前面貌似没用 $JAVA_HOME/bin/java -Dloader.path=$CAF_MODULE_PATHS -jar -Dspring.profiles ...

  6. 【分享一个工具】通过定义proto3来自动生成多进程模式的插件代码

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 我在多进程插件框架 hashicorp/go-plugin ...

  7. 强大的AWS lambda

    AWS强大的lambda 自从几年前换工作后,我所参与的项目一直都是基于AWS云服务的架构,我慢慢对serverless的相关基础建设有了一定了解和实践经验.其中lambda是我心中最强大的serve ...

  8. pycharm的docstring多了一行type

    注释中多了一行:type 设置为Epytext PyCharm 2020.3.5 (Community Edition) def test(param1,param2,param3): "& ...

  9. 从零开始匹配vim(0)——vimscript 简介

    通过之前一系列的文章,相信各位小伙伴应该已经对vim产生了浓厚的兴趣,可能不少小伙伴通过慢慢的使用变的跟我一样,离开vim就不会写代码了.如果你希望继续长时间使用vim,甚至将vim作为主要的代码编辑 ...

  10. TienChin-课程管理-添加课程接口

    CourseController.java @PreAuthorize("hasPermission('tienchin:course:create')") @Log(title ...