看下面的程序:
/** * 功能产生一个整数 */ public abstract class IntGenerator { private boolean cancel = false; public abstract int next(); public void cancel() { this.cancel = true; } public boolean isCancel() { return this.cancel; } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 校验是否为偶数 * */ public class EvenChecker implements Runnable { private IntGenerator intGenerator; private final int id ; public EvenChecker(IntGenerator intGenerator,int ident) { this.intGenerator = intGenerator; this.id = ident; } @Override public void run() { while(!intGenerator.isCancel()) { int val = intGenerator.next(); if (val % 2 != 0) { System.out.println(val + " not even"); intGenerator.cancel(); } } } public static void test(IntGenerator gp,int count) { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < count; i++) { exec.execute(new EvenChecker(gp,i)); } exec.shutdown(); } public static void test(IntGenerator gp) { test(gp,10); } }
/** * 校验产生的数据是否为偶数 * */ public class EvenGenerator extends IntGenerator { /** * currentEvenValue 是个类变量,会存在线程安全 * */ private int currentEvenValue = 0; /** * 这个方法没能使用同步,每个线程在任何时个都能进入方法体 */ @Override public int next() { /** 因此会存在这样一种情况: 一个线程执行了下面行的++操作, 另一个执行return语句,这时next返回的不是一个偶数 */ ++currentEvenValue; ++currentEvenValue; return currentEvenValue; } public static void main(String[] args) { EvenChecker.test(new EvenGenerator()); } }
在多数的情况下,你都能运行一下不为偶数的结果。在我的机器上,多数情况能运行出一个不为偶数的结果,有时不能输出一个结果。
解决这个问题的方法如下:
@Override public synchronized int next() { /** 因此会存在这样一种情况: 一个线程执行了下面行的++操作, 另一个执行return语句,这时next返回的不是一个偶数 */ ++currentEvenValue; ++currentEvenValue; return currentEvenValue; }
next() 加上关键字 synchronized ,表示next() 方法是同步方法,任何时刻只能允许一个线程进行next()方法体。
相关推荐
在本文中,我们将通过一个实例代码来介绍如何使用 Java 多线程来实现多线程切换等待唤醒交替打印奇偶数。 在这个实例中,我们使用 AtomicInteger 来记录奇偶数,我们使用两个线程 A 和 B 来交替打印奇偶数。我们...
实例37 创建多线程应用程序 实例38 多线程的多次加载 实例39 单个线程同步运行 实例40 多线程同步运行 实例41 线程Thread Relative Static跟踪与实现 实例42 线程池(ThreadPool)的应用 实例43 多线程互斥...
以下是一个简单的多线程编程实例: ```java class EvenNumberPrint extends Thread{ @Override public void run() { for (int i = 1; i ; i++) { if(i % 2 == 0){ System.out.println(Thread.currentThread()....
### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...
在Java编程中,多线程是处理并发任务的关键技术,特别是在需要高效利用系统资源和提高程序响应速度的情况下。本文将详细讲解如何使用Java实现多线程轮流打印1-100的数字,以及在此过程中遇到的并发问题及其解决方案...
【Java多线程详解】 Java SE的多线程部分是其核心技术之一,它允许程序同时执行多个任务,提高系统效率。对于新手来说,理解和掌握多线程是成为Java程序员的关键步骤。以下是对Java多线程的详细解释: 1. **程序、...
本实例将详细讲解如何使用Python实现多线程爬虫,以爬取糗事百科上的段子作为具体应用。 首先,我们需要了解普通爬虫的工作方式。在给定的代码片段中,一个简单的Python爬虫被用来获取糗事百科8小时热榜的段子。它...
实例232 多线程同步方法的实例 436 实例233 ATM存取一体机(线程同步互斥) 437 实例234 我的钱哪里去了 440 实例235 门锁打不开了(死锁) 444 实例236 门锁终于被打开了(解决死锁) 446 实例237 一个死锁的例子 ...
实例39 单个线程同步运行 实例40 多线程同步运行 实例41 线程Thread Relative Static跟踪与实现 实例42 线程池(ThreadPool)的应用 实例43 多线程互斥运行 实例44 多线程时钟应用程序 ...
实例39 单个线程同步运行 实例40 多线程同步运行 实例41 线程Thread Relative Static跟踪与实现 实例42 线程池(ThreadPool)的应用 实例43 多线程互斥运行 实例44 多线程时钟应用程序 ...
实例143 使用线程池优化多线程编程 186 实例144 Object类中线程相关的方法 187 实例145 哲学家就餐问题 189 实例146 使用信号量实现线程同步 190 实例147 使用原子变量实现线程同步 191 实例148 使用事件分配线程...
这里,`Dog` 类继承自 `Animal` 类,并重写了 `Speak` 方法,实现了多态性。 5. **异常处理**:C# 使用`try-catch`语句块进行异常处理,确保程序在遇到错误时能够优雅地处理。例如: ```csharp try { int ...
实例27 输出100之间的所有偶数 41 实例28 如何判断回文数字 42 3.4 do…while语句 43 实例29 输出100之间的所有奇数 44 实例30 求最大的随机数 44 3.5 switch语句 45 实例31 判断字母分类 46 ...
实例232 多线程同步方法的实例 436 实例233 ATM存取一体机(线程同步互斥) 437 实例234 我的钱哪里去了 440 实例235 门锁打不开了(死锁) 444 实例236 门锁终于被打开了(解决死锁) 446 实例237 一个死锁的例子 ...
实例27 输出100之间的所有偶数 41 实例28 如何判断回文数字 42 3.4 do…while语句 43 实例29 输出100之间的所有奇数 44 实例30 求最大的随机数 44 3.5 switch语句 45 实例31 判断字母分类...
实例232 多线程同步方法的实例 436 实例233 ATM存取一体机(线程同步互斥) 437 实例234 我的钱哪里去了 440 实例235 门锁打不开了(死锁) 444 实例236 门锁终于被打开了(解决死锁) 446 实例237 一个死锁的...
在Java中,创建和使用线程主要有两种方式,一种是继承Thread类,另一种是实现Runnable接口。这两种方式在使用上有一些区别,每种...掌握这两种方式,以及它们在并发编程中的应用,对于编写有效的多线程程序至关重要。