假如有十张票,现在需要三个窗口(线程)卖,代码如下:
package com.test.runnable; class MyThread implements Runnable { private int ticket = 10; public void run() { while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000l); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
输出结果为:
ticket = 10
ticket = 9
ticket = 8
ticket = 7
ticket = 7
ticket = 7
ticket = 6
ticket = 5
ticket = 6
ticket = 4
ticket = 4
ticket = 3
ticket = 2
ticket = 1
ticket = 2
可以发现不止卖 了十张,所以要进行并发控制。
第一种办法,采用同步关键字
package com.test.runnable; class MyThread implements Runnable { private int ticket = 10; synchronized public void run() { while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
可以发现输出结果为:
ticket = 10
ticket = 9
ticket = 8
ticket = 7
ticket = 6
ticket = 5
ticket = 4
ticket = 3
ticket = 2
ticket = 1
这样多个窗口卖票,就能正确了,
2.也可以采用原子变量
package com.test.runnable; import java.util.concurrent.atomic.AtomicInteger; class MyThread implements Runnable { private AtomicInteger ticket = new AtomicInteger(10); synchronized public void run() { while (ticket.get() > 0) { System.out.println("ticket = " + ticket.getAndAdd(-1)); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
3.采用信号量Semaphore
package com.test.runnable; import java.util.concurrent.Semaphore; class MyThread implements Runnable { final Semaphore semp = new Semaphore(1); private int ticket = 10; public void run() { // 获取许可 try { semp.acquire(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } // 访问完后,释放 semp.release(); } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
4.采用Lock
package com.test.runnable; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class MyThread implements Runnable { private Lock myLock = new ReentrantLock(); // 执行操作所需的锁对象 private int ticket = 10; public void run() { myLock.lock(); while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } // 访问完后,释放 myLock.unlock(); } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
5.但不能采用volatile关键字,因为线程内变量的值更新依赖原值。
package com.test.runnable; class MyThread implements Runnable { //private volatile int ticket = 10; private volatile int ticket = 10; public void run() { while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
相关推荐
在Java并发编程中,主要涉及以下几个关键知识点: 1. **线程与进程**:线程是程序执行的最小单元,一个进程中可以有多个线程同时执行。理解线程的概念和生命周期对于并发编程至关重要。 2. **线程安全**:当多个...
Java 高并发写入用户信息到数据库的几种方法 在 Java 高并发环境下,写入用户信息到数据库可能会出现一些问题,例如多个用户同时写入导致数据不一致或重复写入。为了解决这些问题,需要使用一些特殊的方法来确保...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
2. **同步机制**:详述了Java中同步的几种方法,如`synchronized`关键字、volatile变量、Lock接口(如ReentrantLock)以及Condition。这些机制用于防止数据竞争和确保线程安全。 3. **并发工具类**:Java并发包...
为了解决线程安全问题,Java提供了以下几种机制: - **synchronized关键字**:用于修饰方法或代码块,确保同一时刻只有一个线程可以执行被synchronized修饰的代码。 - **volatile关键字**:用于修饰变量,确保变量的...
Java系统的高并发解决方法详解 ...Java系统的高并发解决方法可以通过静态化、图片服务器分离、数据库集群和库表散列、缓存等多种方法来实现,选择哪种方法需要根据实际情况进行选择和组合,以提高系统的性能和扩展性。
Java并发编程中还需要注意几个重要概念: - 原子性(Atomicity):是指一组操作,要么全部执行成功,要么全部不执行,不能存在执行了部分操作的情况。 - 竞争条件(Race Condition):多个线程对同一数据进行操作时...
本文将从以下几个方面详细讲解Java并发程序设计的核心知识点: 1. 使用线程的经验:线程是并发程序的基础,包括设置线程名称、响应中断信号以及使用ThreadLocal变量。设置线程名称有助于在多线程调试时容易识别线程...
5. **J.U.C框架**:Java并发 utilities (J.U.C) 框架是Java并发编程的重要组成部分,书中会介绍如何利用这个框架来提升并发性能和代码的可读性。 6. **性能调优**:在高并发场景下,性能优化是必不可少的。可能涵盖...
Java并发编程是Java开发者必须掌握的关键技能之一,尤其是在多核处理器和分布式系统广泛使用的今天。以下是对标题和描述中提及的两本经典书籍——《Concurrent Programming in Java》和《Java Concurrency in ...
5. **并发设计模式**:书中详细阐述了几种常见的并发设计模式,如生产者-消费者模型、读写锁策略、工作窃取算法等,这些都是解决并发问题的有效手段。 6. **线程池**:Executor框架是Java并发编程的重要组成部分,...
可以通过以下几种方式来提升系统的并发能力: - **采用分布式架构**:将系统拆分为多个微服务,每个服务独立部署,根据负载情况进行水平扩展。 - **优化数据库性能**:使用读写分离、索引优化等手段提高数据库处理...
Java提供了以下几种线程池实现: 1. FixedThreadPool:固定大小的线程池,如示例所示,核心线程数与最大线程数相同,使用LinkedBlockingQueue作为工作队列,可能导致内存溢出(OOM)如果任务请求过多。 2. ...
在并发控制中,我们通常会遇到以下几个关键概念: - 同步:确保同一时间只有一个线程访问共享资源,防止数据不一致。Java提供了synchronized关键字以及Lock接口(如ReentrantLock)来实现同步。 - volatile:修饰...
Java并发编程的核心知识点包括以下几个方面: 1. **并发基础**:首先,我们需要了解并发的基本概念,如线程、进程、同步和互斥。Java提供了丰富的并发工具类,如Thread、Runnable以及ExecutorService,这些都是进行...
Java并发集合中最核心的几个类包括: 1. **ConcurrentHashMap**:线程安全的哈希映射表,它比synchronized的Hashtable或Collections.synchronizedMap()包装的HashMap有更高的并发性能。ConcurrentHashMap采用了分段...
Java并发编程是Java开发语言中的一个关键领域,特别是在构建高性能、高并发的后端系统时。Apache作为流行的开源软件框架,提供了许多与并发处理相关的工具和库,使得开发者能够更有效地管理和优化多线程环境。本教程...
《Java并发编程实践》这本书是Java开发者深入了解并发编程的重要参考资料,尤其对于想要提升在多线程环境下编程技能的程序员来说,它提供了丰富的实践经验和深入的理论解析。在Java的世界里,多线程是构建高性能、高...
《Java并发编程艺术》是一本深入探讨Java平台上的并发编程技术的专业书籍。这本书全面覆盖了Java并发编程的基础知识、核心概念以及高级技巧,旨在帮助读者理解如何在多线程环境中编写高效、安全的代码。 并发编程是...
5. **并发设计模式**:书中有专门章节介绍了几种常见的并发设计模式,如生产者消费者模式、工作窃取模式、线程池等,以及如何避免和解决并发编程中常见的问题,如死锁、活锁和饥饿。 6. **并发性能优化**:在性能...