`
bo_hai
  • 浏览: 565911 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

多线程产生偶数实例

 
阅读更多

看下面的程序:

 

/**
 * 功能产生一个整数
 */
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()方法体。

分享到:
评论
1 楼 bo_hai 2014-01-12  
将了使用 synchronized 实现锁机制外,还可以使用显示锁来完成上面的功能。代码如下:
在 EvenGenerator 新建:
private Lock lock = new ReentrantLock();

next()方法体的代码如下:

private Lock lock = new ReentrantLock();
/**
 * 这个方法没能使用同步,每个线程在任何时个都能进入方法体
 */
@Override
public int next() {
	/**
	 1、方法进入后,马上就开启锁机制
	 2、return currentEvenValue; 必须在finally 前面,防止过时的取消锁
	 3、代码块必须使用try-- finally 包含,在finally 里面要做的事情是关闭锁
	 */
	lock.lock();
	try {
		++currentEvenValue;
		++currentEvenValue;
		return currentEvenValue;
	} finally {
		lock.unlock();
	}
}


注意事项,在代码的注释中。

相关推荐

    Java 实现多线程切换等待唤醒交替打印奇偶数

    在本文中,我们将通过一个实例代码来介绍如何使用 Java 多线程来实现多线程切换等待唤醒交替打印奇偶数。 在这个实例中,我们使用 AtomicInteger 来记录奇偶数,我们使用两个线程 A 和 B 来交替打印奇偶数。我们...

    Visual.C#.编程精彩百例

    实例37 创建多线程应用程序 实例38 多线程的多次加载 实例39 单个线程同步运行 实例40 多线程同步运行 实例41 线程Thread Relative Static跟踪与实现 实例42 线程池(ThreadPool)的应用 实例43 多线程互斥...

    java多线程基础知识

    以下是一个简单的多线程编程实例: ```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多线程-多线程知识点总结和企业真题

    ### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...

    Java实现多线程轮流打印1-100的数字操作

    在Java编程中,多线程是处理并发任务的关键技术,特别是在需要高效利用系统资源和提高程序响应速度的情况下。本文将详细讲解如何使用Java实现多线程轮流打印1-100的数字,以及在此过程中遇到的并发问题及其解决方案...

    Java SE完整版精品优质课件 自学入门必看的优秀Java基础知识培训教案 第11章_多线程(共54页).pptx

    【Java多线程详解】 Java SE的多线程部分是其核心技术之一,它允许程序同时执行多个任务,提高系统效率。对于新手来说,理解和掌握多线程是成为Java程序员的关键步骤。以下是对Java多线程的详细解释: 1. **程序、...

    Python多线程爬虫实战_爬取糗事百科段子的实例

    本实例将详细讲解如何使用Python实现多线程爬虫,以爬取糗事百科上的段子作为具体应用。 首先,我们需要了解普通爬虫的工作方式。在给定的代码片段中,一个简单的Python爬虫被用来获取糗事百科8小时热榜的段子。它...

    java范例开发大全

    实例232 多线程同步方法的实例 436 实例233 ATM存取一体机(线程同步互斥) 437 实例234 我的钱哪里去了 440 实例235 门锁打不开了(死锁) 444 实例236 门锁终于被打开了(解决死锁) 446 实例237 一个死锁的例子 ...

    《Visual.C#.编程精彩百例》配套光盘.part2

    实例39 单个线程同步运行 实例40 多线程同步运行 实例41 线程Thread Relative Static跟踪与实现 实例42 线程池(ThreadPool)的应用 实例43 多线程互斥运行 实例44 多线程时钟应用程序 ...

    《Visual.C#.编程精彩百例》配套光盘part1

    实例39 单个线程同步运行 实例40 多线程同步运行 实例41 线程Thread Relative Static跟踪与实现 实例42 线程池(ThreadPool)的应用 实例43 多线程互斥运行 实例44 多线程时钟应用程序 ...

    Java范例开发大全 (源程序)

     实例27 输出100之间的所有偶数 41  实例28 如何判断回文数字 42  3.4 do…while语句 43  实例29 输出100之间的所有奇数 44  实例30 求最大的随机数 44  3.5 switch语句 45  实例31 判断字母分类 46 ...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例143 使用线程池优化多线程编程 186 实例144 Object类中线程相关的方法 187 实例145 哲学家就餐问题 189 实例146 使用信号量实现线程同步 190 实例147 使用原子变量实现线程同步 191 实例148 使用事件分配线程...

    c# 实例 c# 实例c# 实例

    这里,`Dog` 类继承自 `Animal` 类,并重写了 `Speak` 方法,实现了多态性。 5. **异常处理**:C# 使用`try-catch`语句块进行异常处理,确保程序在遇到错误时能够优雅地处理。例如: ```csharp try { int ...

    java范例开发大全(pdf&源码)

    实例232 多线程同步方法的实例 436 实例233 ATM存取一体机(线程同步互斥) 437 实例234 我的钱哪里去了 440 实例235 门锁打不开了(死锁) 444 实例236 门锁终于被打开了(解决死锁) 446 实例237 一个死锁的例子 ...

    java范例开发大全源代码

     实例27 输出100之间的所有偶数 41  实例28 如何判断回文数字 42  3.4 do…while语句 43  实例29 输出100之间的所有奇数 44  实例30 求最大的随机数 44  3.5 switch语句 45  实例31 判断字母分类...

    Java范例开发大全(全书源程序)

    实例232 多线程同步方法的实例 436 实例233 ATM存取一体机(线程同步互斥) 437 实例234 我的钱哪里去了 440 实例235 门锁打不开了(死锁) 444 实例236 门锁终于被打开了(解决死锁) 446 实例237 一个死锁的...

    java用线程两种方式

    在Java中,创建和使用线程主要有两种方式,一种是继承Thread类,另一种是实现Runnable接口。这两种方式在使用上有一些区别,每种...掌握这两种方式,以及它们在并发编程中的应用,对于编写有效的多线程程序至关重要。

Global site tag (gtag.js) - Google Analytics