关于火车票案例中 synchronized放在代码哪里的解释:
案例1: 火车票案例
特点: 多窗口下执行的同一个操作动作,使用的同一个公共数据,使用同一个runnable对象
package thread; public class RunnableInUse { /** * 1 业务类传递给 runnable类 runbanle类传递给 thread类 * 2 如果要执行方法是同一个业务方法,那么只需要创建一个runnable类,在这个类里面调动这个业务类的业务方法即可 * 3 如果要执行方法是不同业务方法,那么需要根据业务方法的不同和实际需要来创建对应个数的runnable类,后在thread类里调用不同的runnble类 */ public static void main(String[] args) { MyTicket myTicket = new MyTicket(); new Thread(new MyRunnable1(myTicket)).start(); new Thread(new MyRunnable1(myTicket)).start(); } } class MyRunnable1 implements Runnable{ private MyTicket myTicket; public MyRunnable1(MyTicket myTicket){ this.myTicket = myTicket; } @Override public void run() { myTicket.sellTicket(); } } // 业务方法都要封装在业务类中,方法上加锁 class MyTicket { private int ticketNum = 100; public void sellTicket(){ // 需要在方法内加锁,如果在方法头上加锁,第一个线程进来后直到执行完才能轮到第二个线程,这样就和多窗口买票违背了 while(ticketNum > 1) { synchronized (this) { ticketNum--; System.out.println("出票口" + Thread.currentThread().getName() + "卖票成功,还剩下 " + ticketNum + "个票"); } } } /** * 执行结果: * 出票口Thread-0卖票成功,还剩下 92个票 出票口Thread-0卖票成功,还剩下 91个票 出票口Thread-0卖票成功,还剩下 90个票 出票口Thread-0卖票成功,还剩下 89个票 出票口Thread-0卖票成功,还剩下 88个票 出票口Thread-0卖票成功,还剩下 87个票 出票口Thread-0卖票成功,还剩下 86个票 出票口Thread-0卖票成功,还剩下 85个票 出票口Thread-0卖票成功,还剩下 84个票 出票口Thread-0卖票成功,还剩下 83个票 出票口Thread-0卖票成功,还剩下 82个票 出票口Thread-0卖票成功,还剩下 81个票 出票口Thread-0卖票成功,还剩下 80个票 出票口Thread-0卖票成功,还剩下 79个票 出票口Thread-0卖票成功,还剩下 78个票 出票口Thread-0卖票成功,还剩下 77个票 出票口Thread-0卖票成功,还剩下 76个票 出票口Thread-0卖票成功,还剩下 75个票 出票口Thread-1卖票成功,还剩下 74个票 出票口Thread-1卖票成功,还剩下 73个票 出票口Thread-1卖票成功,还剩下 72个票 出票口Thread-1卖票成功,还剩下 71个票 出票口Thread-1卖票成功,还剩下 70个票 出票口Thread-1卖票成功,还剩下 69个票 */ }
案例2: 设计4个线程,其中两个每次对j加1, 另外两个每次对j减1
特点: 多个线程执行的方法不同,此时需要不同的runnable对象,但是又需要共享同一个数据
总结: 可以用如下方式来实现:
1 将共享数据封装在另一对象中,将这个对象传递给各个runnable对象,
2 线程对共享数据的操作需要分配到这个对象上来完成,对象上的方法增加同步锁,因为所有线程使用同一个对象,因此锁栓一致。
代码:
package thread; public class RunnableInUser2 { /** * 两个线程对变量递增 * 两个线程对变量递减 */ public static void main(String[] args) { AddAndDelete addAndDelete = new AddAndDelete(); for(int i=0; i<4;i++){ new Thread(new AddRunnable(addAndDelete)).start(); new Thread(new DeleteRunnable(addAndDelete)).start(); } } } class AddRunnable implements Runnable{ private AddAndDelete addAndDelete; public AddRunnable(AddAndDelete addAndDelete){ this.addAndDelete = addAndDelete; } @Override public void run() { addAndDelete.addOne(); } } class DeleteRunnable implements Runnable{ private AddAndDelete addAndDelete; public DeleteRunnable(AddAndDelete addAndDelete){ this.addAndDelete = addAndDelete; } @Override public void run() { addAndDelete.deleteOne(); } } class AddAndDelete{ private int num = 0; public synchronized void addOne(){ System.out.println("addOne, the result is" + num++); } public synchronized void deleteOne(){ System.out.println("deleteOne, the result is" + num--); } /** * addOne, the result is0 deleteOne, the result is1 addOne, the result is0 deleteOne, the result is1 addOne, the result is0 deleteOne, the result is1 addOne, the result is0 deleteOne, the result is1 */ }
脑图:
相关推荐
一个简单的多线程代码示例,Java实现,用于实现同一时刻,只允许一个线程调用执行的代码块或类,即synchronized的如何使用(多线程实现),实现 Runnable
Java多线程--创建多线程的基本方式二:实现Runnable接口
add 实验一:多线程/2.Runnable接口. 实验八:JDBC数据库编程二——存储过程与函数 add 实验八:JDBC数据库编程二——存储过程与函数/2.addTwoNumAndReturn. 实验十:Socket编程 add 实验十:Socket编程/...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
在Java中只支持单继承,因此通过继承Thread类创建线程有一定的局限性,这时可以使用另一种方式,即实现Runnable接口来创建线程。通过这种方式需要在Thread(Runnable target)的构造方法中,传递一个实现了Runnable...
基于JAVA的多线程实现方法-实现Runnable接口 将需要实现多线程的类声明为实现Runnable接口的类,实现run()方法,并将线程体放在该方法里。
本文首先介绍了线程的有关概念,接着介绍了线程的生命期及其状态间的转换,多线程的调度 原则,线程的死锁,详细阐述了多线程的两种实现方法: 由Thread类派生子类;实现Runnable接口
由于用了LinkedList数据结构,省去了相当多的麻烦。 *************************************************************************/ //---------------------------------------------------------------------- //...
2. 使用 runnable 接口实现按两个不同的时间间隔( 1 秒和 3 秒)在屏幕上显示当前时间。 3.写一个程序,模拟4个售票窗口共同卖100张火车票的程序。 使用继承Thread类方式和实现Runnable接口两种方式实现。
计算机后端-Java-Java核心基础-第20章 多线程 09. 同步方法处理实现Runnable的线程安全
一、实验目的 掌握多线程程序设计 二、实验环境 1、微型计算机一台 2、WINDOWS操作系统,Java SDK,Eclipse开发环境 三、实验内容 ...3、采用线程同步方法机制来解决多线程共享冲突问题,编写示例程序。
使用方法如下: //0. listView = (ListView)findViewById(R.id.listView1); final TestAdapter testAdapter = new TestAdapter(); //1.获取DownloadManager实例 建议在application中初始化 final Download...
java多线程runnable实例,经过测试的,可以直接运行
在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。
在一个线程中求100以内的偶数,求出一个偶数后休眠一个随机时间在(1-300毫秒之间).在另一个线程中求奇数,求出一个奇数后也休眠一个随机时间(1-300毫秒之间).输出数据时应有提示,指明是哪个线程输出的数据 用实例...
C#多线程,System.Threading.Thread类,线程同步等
请使用“匿名Runnable”子类的方式实现线程,线程中计算1--500所有数字的累加和,并打印计算结果
Java中的多线程有三种实现方式: 1.继承Thread类,重写run方法。Thread本质上也是一个实现了Runnable的实例,他代表一个线程的实例,并且启动线程的唯一方法就是通过Thread类的start方法。 2.实现Runnable接口,并...
本章内容 掌握同步代码块的使用 掌握同步方法的使用 理解线程死锁 掌握 ThreadLocal 类的使用 使用多线程模拟猴子采花 使用同步方法模拟购票 使用多线程模拟购物订单生成 使用 ThreadLocal 类模拟银行取款 Java高级...
声明自定义线程类实现Runnable接口实现奇数/偶数序列线程并发执行。