前言
网上有多关于“JAVA多线程”的文章,但是对于不太熟悉多线程的编程人员来说人来说太抽象了,干脆我就直接用代码告诉大家何为多线程,不同的编写方式会带来怎样的后果以及如何正确的使用多线程。
示例程序功能描述
SynchronizedDemo.java业务功能:模拟火车售票场景。成员变量total表示火车表总量。showToal()一旦被执行就开始卖表(total-1),票没了(当total的值小于等于零)就停止卖票。
业务代码及执行结果
/** * 模拟火车售票场景。成员变量total表示火车表总量。showToal()一旦被执行就开始卖表(total-1),票没了(当total的值小于等于零)就停止卖票 * @author 许井龙 * */ public class SynchronizedDemo implements Runnable { /* 火车票总量*/ private static int total = 100; /** * 程序入口 * @param args */ public static void main(String[] args) { //模拟八个售票窗口 Thread td1 = new Thread(new SynchronizedDemo()); Thread td2 = new Thread(new SynchronizedDemo()); Thread td3 = new Thread(new SynchronizedDemo()); Thread td4 = new Thread(new SynchronizedDemo()); Thread td5 = new Thread(new SynchronizedDemo()); Thread td6 = new Thread(new SynchronizedDemo()); Thread td7 = new Thread(new SynchronizedDemo()); Thread td8 = new Thread(new SynchronizedDemo()); //八个售票窗口同时售票; td1.start(); td2.start(); td3.start(); td4.start(); td5.start(); td6.start(); td7.start(); td8.start(); } @Override /** * 多线程执行入口 */ public void run() { //售票:稍后会有不同的具体实现 showToal(); } }如果showToal()代码如下,
public void showToal(){ //long sTime = System.currentTimeMillis(); while(true){ //当总量(total)当小于等于0的时候,就不能在继续减少了 if(total>0){ try { //模拟线程阻塞1ms Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } total = total - 1; System.out.println(Thread.currentThread().getName() + " 余票: " + total + "张"); }else{ //反之结束程序 break; } } //System.out.println(Thread.currentThread().getName() + "耗时:" + (System.currentTimeMillis() - sTime)/1000); }执行结果如下,
.... Thread-4 余票: 5张 Thread-1 余票: 4张 Thread-0 余票: 3张 Thread-3 余票: 0张 Thread-5 余票: 1张 Thread-2 余票: 2张 Thread-7 余票: -1张 Thread-1 余票: -2张 Thread-6 余票: -3张 Thread-4 余票: -4张余票居然出现了负数,显然是我们程序出现了漏洞。聪明的你马上就意识到,showTota()没有使用synchronized。因此你修改了showTota(),
public synchronized void showToal(){ //long sTime = System.currentTimeMillis(); while(true){ // 当总量(total)当小于等于0的时候,就不能在继续减少了 if(total>0){ try { //模拟线程阻塞1ms Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } total = total - 1; System.out.println(Thread.currentThread().getName() + " 余票: " + total + "张"); //反之结束程序 }else{ break; } } //System.out.println(Thread.currentThread().getName() + "耗时:" + (System.currentTimeMillis() - sTime)/1000); }但是我们看看运行结果,
Thread-5 余票: 4张 Thread-2 余票: 4张 Thread-4 余票: 6张 Thread-6 余票: 6张 Thread-3 余票: 6张 Thread-0 余票: 2张 Thread-7 余票: 2张 Thread-4 余票: -3张 Thread-1 余票: -4张 Thread-2 余票: -4张 Thread-3 余票: -3张 Thread-5 余票: -3张 Thread-6 余票: -3张 Thread-0 余票: -6张 Thread-7 余票: -6张似乎和你预期的不太一样哦。那么是synchronized没生效?还是我们使用的不对呢?现在我告诉你:showToal()需要声明为static。
相关推荐
Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,从而提高应用程序的效率和响应性。本教程将深入讲解Java线程的相关知识,包括进程与线程的基本概念、线程的创建和启动、多线程的互斥与同步、线程...
在解决Java Swing多线程死锁问题时,我们需要了解Java Swing的多线程机理和相关API的使用。SwingUtilities.invokeLater和SwingUtilities.isEventDispatchThread()是我们解决死锁问题的重要工具。 在实际开发中,...
哲学家就餐问题是多线程编程中一个经典的同步问题。该问题描述为五位哲学家围坐在一张圆桌旁,桌上放着五个筷子(或者说是餐叉),每个哲学家在思考的时候不使用筷子,而当他们想吃饭时,则需要同时拿到左右两边的...
【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗...
2、支持多任务多线程同时下载; 3、每个任务的线程数由用户在新建任务时自定义,缺省为5个线程; 4、任务下载过程中可以点击“线程+”或“线程-”即时增减线程; 5、选择任务,可以在任务信息栏中查看任务下载的信息...
5. **多线程编程**: Java2引入了丰富的多线程支持,包括Thread类、synchronized关键字、wait/notify机制等。源码分析可以帮助理解线程同步和通信,避免并发问题。 6. **输入/输出与网络编程**: Java2提供了强大...
本教程聚焦于JAVA基础和IDEA的使用,同时也涵盖了多线程的概念以及IDEA的卸载过程。 首先,让我们来探讨JAVA基础。Java是一门面向对象的编程语言,以其“一次编写,到处运行”的特性而闻名。它的核心概念包括类、...
首先,我们需要了解Java中的流。在Java中,I/O操作是通过流来完成的,流可以看作数据传输的通道。流分为两种类型:输入流(InputStream)用于读取数据,输出流(OutputStream)用于写入数据。根据处理的数据类型,流...
本章主要介绍多线程编程的基础知识,包括并发与多线程的概念、多线程编程的重要性、线程的运行机制、并发编程面临的挑战以及如何使用Java中的线程进行编程。 现代计算机具有多个核心,通常为5-10个,但也有如Intel...
Java 是一种简单的、跨平台的、面向对象的、分布式的、解释的、健壮的安全的、结构的中立的、可移植的、性能很优异的多线程的、动态的语言。Java 语言的出现彻底改变了互联网上的信息内容,让我们的互联网丰富多彩...
### 彻底理解Java语言中的IO系统 #### 一、Input和Output Java IO系统是Java编程中的一个重要组成部分,它负责处理程序与外部资源(如文件、网络等)之间的数据交换。Java IO的设计以流为基础,可以分为输入流...
6. **多线程**:Java API提供了强大的多线程支持,包括`java.lang.Thread`类和`java.util.concurrent`包中的并发工具类,如`ExecutorService`和`Semaphore`。 7. **Lambda表达式和函数式编程**:Java 8引入了lambda...
4. **日期和时间API**:Java8彻底改变了日期和时间的处理,引入了`java.time`包,提供了更直观、更易用的API,如`LocalDate`、`LocalTime`、`LocalDateTime`等,替代了原来的`java.util.Date`和`Calendar`。...
- **多线程支持总结**:总结Java多线程支持的优点和应用场景。 #### 8. 性能和比较 ##### 8.1 性能 - **性能因素**:讨论影响Java程序性能的因素及其优化策略。 ##### 8.2 Java语言的比较 - **与其他语言的比较**...
2. **JVM内存模型**:了解Java内存分配和回收的过程,以及老年代在整个内存管理中的角色。 3. **并发编程**:理解CMS如何在多线程环境下保证垃圾收集的正确性。 4. **性能优化**:学习如何调整CMS参数以达到最佳的...
Java内存模型是Java多线程编程中的核心概念,它规定了如何处理线程间的共享变量访问,以确保数据的一致性和正确性。本文主要探讨了Java内存模型从早期到JDK5之后的历史变迁。 在旧的Java内存模型中,线程通过共享...
- **原子操作与变量**:原子操作是指一个不可中断的操作,即使在多线程环境下也能保证完整性。Java 8通过`java.util.concurrent.atomic`包提供了一组原子变量类,如`AtomicInteger`。 - **共享内存与消息传递**:...
4. **多线程与并发**:为了提高爬虫的效率,通常会采用多线程或异步处理。Java的并发库提供了丰富的工具,如ExecutorService、Future、Callable等,用于管理和协调多个任务。 5. **爬虫框架**:如Jsoup+CrawlingKit...
在上一篇讲CompletableFuture的文章中,我们了解了CompletableFuture提供的串行、并行等常用异步编排的方案。但是,在细节上还是有许多不足,比如回调方面,编排复杂顺序方面。因此,我们需要一种更加强大且灵活的...