`
bo_hai
  • 浏览: 554891 次
  • 性别: 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 实现多线程切换等待唤醒交替打印奇偶数 ,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    Visual.C#.编程精彩百例

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

    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开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

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

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

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

    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经典编程300例(完整版+源码

    多线程、 网络通信和数据库操作。 本书所精选的实例都是一线开发人员在实际项目中所积累的,并进行了技术上的解析,给出了详细的实现过程。读者通过对本书的学习,能够提高开发的能力。 本书提供了大量的源程序、...

    (多线程)leetcode1115. 交替打印FooBar 记得Thread.yield();

    我们提供一个类: ...两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。 请设计修改程序,以确保 “foobar” 被输出 n 次。 示例 1: 输入

    java 算法

    多线程的世界时钟,显示巴黎,罗马,上海时间, AWT界面,Java日期格式化及其使用例子,几个常用方法,判断字符是否属于中文,异常处理类,去掉字符串中重复的子字符串,将指定byte数组以16进制的形式打印到控制台,...

    Silverlight2.0功能展示Demo源码

    Silverlight 2.0 使用Thread, Timer, BackgroundWorker, ThreadPool来实现多线程开发。 Thread - 用于线程的创建和控制的类 Timer - 用于以指定的时间间隔执行指定的方法的类 BackgroundWorker - 用于在单独的线程上...

    Python3 菜鸟查询手册

    25.11 判断奇数偶数.png 25.12 判断闰年.png 25.13 获取最大值函数.png 25.14 质数判断.png 25.15 输出指定范围内的素数.png 25.16 阶乘实例.png 25.17 九九乘法表.png 25.18 斐波那契数列.png 25.19 ...

    asp.net面试题

    答:进程是老子,线程是儿子,没有老子就没有儿子,一个老子可以有多个儿子.一个儿子可以成为别人的儿子,一个老子也可以为别的老子生儿子. 13.什么是code-Behind技术。 答:代码分离,这是个明智的东西,像ASP这样混成一...

Global site tag (gtag.js) - Google Analytics