编程-java 线程问题,谢谢大家了。

问题描述

java 线程问题,谢谢大家了。
public class Vs {
public static int count = 0;

public synchronized static void inc() {    //这里延迟1毫秒,使得结果明显        try {            Thread.sleep(1);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        count++;}public static void main(String[] args) {    //同时启动1000个线程,去进行i++计算,看看实际结果    for (int i = 0; i < 1000; i++) {        new Thread(new Runnable() {            @Override            public void run() {                Vs.inc();            }        }).start();    }    System.out.println(""运行结果:Counter.count="" + Vs.count);}

}

问题:为什么Synchronized没能将方法锁住。
加了Synchronized后得出的结果大概是一百多
去掉Synchronized后的结果大概是九百多
为什么会有这样的差异?

解决方案

不是没锁住,是因为线程是异步的

  System.out.println(""运行结果:Counter.count="" + Vs.count);执行这句的时候线程还没执行完

你在

 public synchronized static void inc() {    //这里延迟1毫秒,使得结果明显        try {            Thread.sleep(1);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        count++;                 System.out.println(""运行结果2222:Counter.count="" + count);//这里加一句,最后一个肯定是1000}

解决方案二:
可以再读一读java线程运行的有关知识,启动只是将其加入到执行队列中,并不是立即开始执行该线程,你输出的时候看到的结果并不是最终所有1000个线程都执行一次的结果,你的结果其实更说明了synchronized的作用,加了之后运行时必须等待其他已经执行的线程执行完才能执行,速度下降了,而没有加时,是不用等待的,执行速度更快等到的结果更大。

解决方案三:
1楼网友是正确的。主要是因为我们自己起的线程和主线程是并列执行的。

解决方案四:

 public static void main(String[] args) {        //设置启动的总线程数        int number = 1000;        //创建倒数锁存器        final CountDownLatch doneSignal = new CountDownLatch(number);        //同时启动1000个线程,去进行i++计算,看看实际结果        for (int i = 0; i < number; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    Vs.inc();                    //每个线程执行完自动减1                    doneSignal.countDown();                }            }).start();        }        try {            //在总数没减到0之前,使主线程(main线程一直等待)            doneSignal.await();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(""运行结果:Counter.count="" + Vs.count);    }

解决方案五:
恰恰相反,inc方法其实已经被锁住了,你之所以没有得到1000这个正确的数据是因为你的支线程还在等待线程锁的释放,主线程就已经结束了。你可以在主线程打印count之前先休眠一定时间,结果一定是1000。(从你得到100多这个数据可以看出你的cpu肯定不怎么好,,)

解决方案六:
恰恰相反,inc方法其实已经被锁住了,你之所以没有得到1000这个正确的数据是因为你的支线程还在等待线程锁的释放,主线程就已经结束了。你可以在主线程打印count之前先休眠一定时间,结果一定是1000。(从你得到100多这个数据可以看出你的cpu肯定不怎么好,,)

解决方案七:
加了Synchronized了后得出的结果大概是一百多,说明是

解决方案八:
你没保证所有线程已经执行完就把结果打印出来了,保证所有线程已经执行结束并且加了关键字之后肯定是1000

解决方案九:
同意1楼,主线程也是一个线程。

解决方案十:
恰恰相反,inc方法其实已经被锁住了,你之所以没有得到1000这个正确的数据是因为你的支线程还在等待线程锁的释放,主线程就已经结束了。你可以在主线程打印count之前先休眠一定时间,结果一定是1000。(从你得到100多这个数据可以看出你的cpu肯定不怎么好,,)

时间: 2024-09-08 06:40:24

编程-java 线程问题,谢谢大家了。的相关文章

编程-java菜鸟程序员提问:求大神给我说说线程在什么场景下用,以及多线程工作原理。谢谢

问题描述 java菜鸟程序员提问:求大神给我说说线程在什么场景下用,以及多线程工作原理.谢谢 现在java线程编程应用广泛吗?哪些时候适合或必须要用多多线程编程呢?多线程的工作原理是怎样的呢?求大神们指导指导,谢了! 解决方案 (1)线程的工作场景主要有两条: 一个是并发操作,避免阻塞和更有效利用资源.典型的例子有:在长时间工作的程序中使用工作线程避免界面失去响应.在网络下载程序中,使用多个线程提高对网络的使用效率,更快下载文件. 一个是并行,线程是处理器调度的最小单位.如果你的计算机配置了多个

java线程编程(一):线程基础

在学习java中,我发现有关于对线程的讲解比较少,我打算为一些java初学者提一些关于线程方面的参考, 为深入学习java奠定基础.我本着共同进步的原则特写下了关于java线程编程的一系列文章 java线程编程(一):线程基础 ◆线程(thread)其实是控制线程(thread of control)的缩写. 每一个线程都是独立的,因此线程中的每个方法的局部变量都是和其他线程隔离开的,这些变量完全是私有的,因此对于 线程而言,是没有办法访问其他线程的局部变量的.如果两个线程同时访问同一个方法,则

《Java线程与并发编程实践》—— 导读

前言 Java线程与并发编程实践 线程和并发工具并非尤物,但是它们是正式应用的重要部分.本书会向你介绍Java 8 Update 60中线程特性以及并发工具的大部分内容. 第1章介绍了类Thread和接口Runnable.你会学习如何创建Thread以及Runnable对象,获取和设置线程状态.启动线程.中断线程,将一条线程插入另外一条线程以及触发线程睡眠. 第2章关注同步.学习后你会解决一些问题,如没有同步就无法解决的竞态条件.你也能学到如何创建同步方法.块,以及如何使用忽略互斥访问的轻量级同

详解Java多线程编程中线程的启动、中断或终止操作_java

线程启动: 1.start() 和 run()的区别说明start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用. run() : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程! 下面以代码来进行说明. class MyThread extends Thread{ public void run(){ ... } }; MyThread mythread = new

《 Java并发编程从入门到精通》 Java线程池的监控

本文是< Java并发编程从入门到精通>第9章 线程的监控及其日常工作中如何分析的9.1节 Java线程池的监控.   看不到不等于不存在!让我们来看看工作中是如何找问题解决问题的. 鸟欲高飞先振翅,人求上进先读书. 京东,亚马逊,当当均有销售. 9.1 Java线程池的监控 如果想实现线程池的监控,必须要自定义线程池继承ThreadPoolExecutor类,并且实现beforeExecute,afterExecute和terminated方法,我们可以在任务执行前,执行后和线程池关闭前干一

详解Java编程中线程同步以及定时启动线程的方法_java

使用wait()与notify()实现线程间协作 1. wait()与notify()/notifyAll()调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁.这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中.可以通过notify()/notifyAll(),或者时间到期,从wait()中恢复执行. 只能在同步控制方法或同步块中调用wait().notify()和notifyAll().如果在非同步的方法里调用这些方法,在运

《Java线程与并发编程实践》—— 第2章 同步 2.1 线程中的问题

第2章 同步 Java线程与并发编程实践 线程交互通常是通过共享变量完成的,当线程之间没有交互时,开发多线程的应用程序会变得简单许多.一旦发生了交互,很多诱发线程不安全(在多线程环境下不正确)的因素就会暴露出来.在这一章中,你将会认识到这些问题,同时也会学习如何正确地使用Java面向同步的特性来克服它们. 2.1 线程中的问题 Java对线程的支持促进了响应式.可扩展应用程序的发展.不过,这样的支持是以增加复杂性作为代价的.如果不多加小心,你的代码就会到处充斥着极难以察觉的bug,而这些bug多

Java并发编程:线程池的使用(转)

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

《Java线程与并发编程实践》- 第1章 Thread和Runnable

第1章 Thread和Runnable Java线程与并发编程实践 Java程序是通过线程执行的,线程在程序中具有独立的执行路径.当多条线程执行时,它们彼此之间的路径可以不同.举个例子,一条线程可能在执行switch语句的某个case分支,另一条线程很可能在执行其他case分支. 每个Java应用程序都有一个执行main()函数的默认主线程.应用程序也可以创建线程在后台操作时间密集型任务,以确保对用户的响应.这些封装了代码执行序列的线程对象就被称为runnable. Java虚拟机给每条线程分配