我是新人,关于Java线程的问题,很简单的例子,可是我就是调不出来,不知道哪里错了

问题描述

我想试一下synchronized关键字是不是有效?所以写了一个很简单的类,但是就是不能调到数字按序排列。不知道错在哪里了。数字序列类:package com.testthread;public class UnsafeSequence {private int value = 0;public synchronized int getValue(){value = value+1;return value;}}线程类package com.testthread;public class TestThread extends Thread {private UnsafeSequence us;public TestThread(UnsafeSequence us, String threadname) {super(threadname);this.us = us;}@Overridepublic void run() {String classname = this.getClass().getSimpleName();String threadname = currentThread().getName();for (int i = 0; i < 5; i++) {System.out.println(classname + "[" + threadname + "]:"+ us.getValue());}}}Main类package com.testthread;public class MainClass {public static void main(String[] args) throws InterruptedException {System.out.println("Main started");UnsafeSequence us = new UnsafeSequence();TestThread at = new TestThread(us,"at");TestThread bt = new TestThread(us,"bt");at.start();bt.start();System.out.println("Main ended");}}可是结果是:Main startedMain endedTestThread[bt]:2TestThread[bt]:3TestThread[at]:1TestThread[at]:5TestThread[at]:6TestThread[at]:7TestThread[at]:8TestThread[bt]:4TestThread[bt]:9TestThread[bt]:10我想让数字按序排列,可是数字没有按序排列,请问哪里写错了,谢谢 问题补充:我的机器是多核cpu,会不会和多核cpu有关呢?

解决方案

你真要输出1-10的话,应该在UnsafeSequence.getValue里面输出value的值,肯定就是1-10了,因为System.out.println的执行和getValue的执行是两个方法的调用,getValue方法调用返回以后,不一定它就马上执行了System.out.println,因为这个时候可能又转到别的线程执行去了,加synchronized唯一能保证的是,getValue无论多少个线程同时调用,他一定会序列化执行,也就是在这里输出value的值,一定是递增的。
解决方案二:
你的问题是这样的 楼上的已经说的很清楚了 我在简单说一下 若多个线程 同时跑到 System.out.println(classname + "[" + threadname + "]:" + us.getValue()); 这句话 这时 方法getValue()会有锁 所以只能一个线程进去 但是 并不能保证谁先输出结果 所以顺序会乱修改: 1.去掉 getValue()方法前的 Synchronized 2.synchronized (us) {System.out.println(classname + "[" + threadname + "]:"+ us.getValue()); }(在输出那句话上 用synchronized锁定 这样保证 一个一个的进入)
解决方案三:
public class UnsafeSequence {private AtomicInteger value = new AtomicInteger(0);public int getValue() {return value.incrementAndGet();}public static void main(String[] args) {System.out.println("Main started");UnsafeSequence us = new UnsafeSequence();TestThread at = new TestThread(us, "at");TestThread bt = new TestThread(us, "bt");at.start();bt.start();System.out.println("Main ended");}}class TestThread extends Thread {private UnsafeSequence us;public TestThread(UnsafeSequence us, String threadname) {super(threadname);this.us = us;}@Overridepublic void run() {String classname = this.getClass().getSimpleName();String threadname = currentThread().getName();for (int i = 0; i < 10; i++) {synchronized (us) {System.out.println(classname + "[" + threadname + "]:" + us.getValue());}}}}
解决方案四:
概念混淆了吧,synchronized只能保证同一时刻共享资源被唯一访问,可没说能排序啊

时间: 2024-09-14 13:43:41

我是新人,关于Java线程的问题,很简单的例子,可是我就是调不出来,不知道哪里错了的相关文章

循环 变量定义-java初学问题,很简单的

问题描述 java初学问题,很简单的 import java.util.Scanner;public class Za {private static final double sum = 0; public static void main(String[] args) { int score[]=new int[5]; int sum=0; for (int i = 0; i < score.length; i++) { System.out.println(""请输入成绩:

写给新人:撰写推广方案其实很简单

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 导读:笔者也是个半新不旧的人,在从事推广行业这么一段时间以来,曾经比较头大的就是怎么去写推广方案?开始写的时候总是觉得没什么好写的,要么写的太简单太短,要么就是长篇大论弄偏题了.所以一直对写方案很抵触,可是后来才知道这样逃避是不行的,因为根本躲不过去.硬着头皮写啊写,到最后终于豁然了,原来撰写推广方案其实很简单. 网站推广是企业网络营销的核心

JAVA线程的三种简单实现

JAVA并发编程的书有很多,对我胃口的就这一本:<Java并发编程从入门到精通>. 不厚,但从入门讲起. 今天实践了三种线程的简单实现. ThreadA package demo.thread; public class ThreadA extends Thread { public void run() { super.run(); try { Thread.sleep(500L); } catch (InterruptedException e) { e.printStackTrace()

java 字符串相减(很简单的一个方法)

本篇文章是对java中关于字符串相减的一个简单的方法进行了介绍,需要的朋友参考下   有个比较简单的方法: 复制代码 代码如下: str1="abcd"; str2="cd"; str3=str1.replaceAll(str2,""); //str3="ab"

如何中断JAVA线程

如何中断JAVA线程 程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误.       在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程.                                                                                      背景     中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,

Java线程:新特征-有返回值的线程

在Java5之前,线程是没有返回值的,常常为了"有"返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了. 现在Java终于有可返回值的任务(也可以叫做线程)了. 可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口. 执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了. 下面是个很简单的例子: import java.util.concurrent.*

JavaSE学习总结(五)——封装,继承,多态很简单

java面向对象的三大特性是:封装.继承与多态,是面向对象编程的核心. 一.封装 简单说封装就是将同一类事物的特性与功能包装在一起,对外暴露调用的接口. 封装:封装也称信息隐藏,是指利用抽象数据类型把数据和基于数据的操作封装起来,使其成为一个不可分割的整体,数据隐藏在抽象数据内部,尽可能的隐藏数据细节,只保留一些接口使其与外界发生联系.也就是说用户无需知道内部的数据和方法的具体实现细节,只需根据留在外部的接口进行操作就行. 封装的好处: 1) 实现了专业的分工 2) 良好的封装能够减少耦合 3)

我是新人,请问论坛内是否有JAVA相关的视频教程以及书籍可以下载?

问题描述 我是新人,请问论坛内是否有JAVA相关的视频教程以及书籍可以下载?给两个下载链接? 解决方案 解决方案二:百度一下有很多的尚学堂解决方案三:传智播客的还不错

Java线程模型缺陷研究

Java 编程语言的线程模型可能是此语言中最薄弱的部分.它完全不适合实际复杂程序的要求,而且也完全不是面向对象的.本文建议对 Java 语言进行重大修改和补充,以解决这些问题. Java 语言的线程模型是此语言的一个最难另人满意的部分.尽管 Java 语言本身就支持线程编程是件好事,但是它对线程的语法和类包的支持太少,只能适用于极小型的应用环境. 关于 Java 线程编程的大多数书籍都长篇累牍地指出了 Java 线程模型的缺陷,并提供了解决这些问题的急救包(Band-Aid/邦迪创可贴)类库.我