java 多线程同步可一理解为多个单线程运行吗?

2024-12-15 21:22:07
推荐回答(4个)
回答1:

不知道上面的粘贴那一堆东西有毛用............越看会越糊涂....
你的问题里有两个关键词, 1,是多线程, 2, 是同步.
首先,我们要了解为什么要有多线程?多线程出现的目的是什么?解决了什么问题?

java是运行在一个java虚拟机里面,而我们的程序希望是能够及时响应的,比如我们用程序做了一个计算器.那么,如果一直是顺序执行,那么,当我在计算一个耗时特别大的运算任务的时候,界面上就会没有响应.只能等到计算完毕,举个例子,就像是,我们的电脑卡了,某个windows窗口上出现了,(无响应)这个讨厌的字眼. 非常令用户痛苦. 所以,就出现了多线程,让一个线程去计算去吧.我们的界面依然可以相应你的需求,然后当计算线程结束后,再把结果返回过来,显示在界面上就好.

这是多线程出现的原因.
那么他的原理是什么呢? 那么你需要了解一下cpu时间片的概念. 简单说一下,cpu是用来运算的,但是,程序里面不可能一直是运算,这个程序可能还要等待用户输入信息,或者等待io或者等待数据下载完成,然后才能计算. 而这些等待的时候,cpu其实就被浪费了.那么,我们的多线程,多进程也都应景而生了, cpu吧执行时间分成了许多时间片. 程序需要等io等等不需要cpu的操作的时候.那么,就把时间片分给别的需要cpu计算的程序/线程. 这样,就能最大化利用cpu 同时,也解决了,(无响应)这个问题.可以同时运行多个进程/线程 .
那么当多线程出现了之后,又出现了问题.什么问题呢?
还是用计算器这个例子. 我们要用计算器来计算,数据,假设,我们的加减法用一个线程执行,乘除法用另外一个线程执行.那,我们怎样保证不出现脏数据?
. 被加数/被乘数 这个数字是两个线程公用的东西. 我们称这个数字为 临界资源. 需要抢着用的东西.
会出现一种这样的情况, a线程读了这个数字,然后b也读了这个数字,a计算后,将结果赋值给这个数字,而之后b也计算完了,也把值赋值给了这个数字,这时候,我们发现,a的计算结果,就被b的计算结果给覆盖了,等于没有计算a. 对于这种情况我们怎么解决?
那么,我们就需要用同步的方法.来规范程序.只能同时有一个人来操作这个数字.
我们会通过对象锁,当a要计算之前,会先把这个数字锁定,然后计算.而此时b来了,发现这个数字已经被锁了,所以,就在外面等着.直到a计算结束,把结果赋值给了这个数字,然后解锁, 此时,b才会拿到这个结果,来进行计算.这样就保证了,不会出现脏数据.

.........以为会很简单.打啊打的.结果.打了这么多.......
加油吧,亲,面包会有的,一切都会有的

回答2:

一个进程又可以包含一个或多个线程,一个线程就是一个程序内部的一条执行线索。在单线程中,程序代码按调用顺序依次往下执行,在这种情况下,当主函数调用了子函数,主函数必须等待子函数返回后才能继续往下执行,不能实现两段程序代码同时交替运行的效果。如果要一程序中实现多段代码同时交替运行,就需产生多个线程,并指定每个线程上所要运行的程序代码,这就是多线程。

回答3:

不可以,单线程相当一个人完成一个任务,而多线程相当几个人完成一个任务

回答4:

程序、进程和线程:
程序是一段静态的代码,它是应用程序执行的蓝本。进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕
的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。线程是比进程更小的单位,一个进程执行过程中可以产生多个线程,每个线程有自身的产生、
存在和消亡的过程,也是一个动态的概念。每个进程都有一段专用的内存区域,而线程间可以共享相同的内存区域(包括代码和数据),并利用这些共享单元来实现
数据交换、实时通信与必要的同步操作。

每个Java程序都有一个默认的主线程。Java程序总是从主类的main方法开始执行。当JVM加载代码,发现main方法后就启动一个线程,这个线程就称作"主线程",该线程负责执行main方法。在main方法中再创建的线程就是其他线程。
如果main方法中没有创建其他线程,那么当main方法返回时JVM就会结束Java应用程序。但如果main方法中创建了其他线程,那么
JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法返回(主线程结束)JVM也不会结束,要一直等到该程序所
有线程全部结束才结束Java程序(另外一种情况是:程序中调用了Runtime类的exit方法,并且安全管理器允许退出操作发生。这时JVM也会结束
该程序)。

线程的状态与生命周期:
Java使用java.lang.Thread类及其子类的对象表示线程,新建的线程在它的一个完整生命周期中通常要经历如下四种状态:(新建、运行、(中断/挂起/阻塞)、消亡)
1、新建:
当一个Thread类或其子类对象被声明并创建,新生的线程对象就处于新建状态(此时它已经有了内存空间和其他资源)。

2、运行:
线程已经创建就具备了运行的条件,一旦轮到它来享用CPU资源时,即JVM将CPU使用权切换给该线程时,此线程就可以脱离创建它的主线程独立开始自己的生命周期了。
线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法(从父类继承)通知JVM,这样JVM就知道又有一个新的线程排队等候切换。
当JVM将CPU使用权切换给线程时,如果线程是Thread的子类创建的,该类中的run()方法立刻执行(run()方法中规定了该线程的具
体使命)。Thread类中的run()方法没有具体内容,程序要在Thread类的子类中重写run()方法覆盖父类该方法。(注意:在线程没有结束
run()方法前,不要再调用start方法,否则将发生ILLegalThreadStateException异常)

3、挂起:
线程挂起的原因有一下四种:
(1)、JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权,并处于挂起状态。
(2)、
线程使用CPU资源期间,执行了sleep(int millsecond)方法,使当前线程进入休眠状态。sleep(int
millsecond)方法是Thread类中的一个类方法,线程执行该方法就立刻让出CPU使用权,进入挂起状态。经过参数millsecond指定的
毫秒数之后,该线程就重新进到线程队列中排队等待CPU资源,然后从中断处继续运行。
(3)、线程使用CPU资源期间,执行了wait()方法,使得当前线程进入等待状态。等待状态的线程不会主动进入线程队列等待CPU资源,必须由其他线程调用notify()方法通知它,才能让该线程从新进入到线程队列中排队等待CPU资源,以便从中断处继续运行。
(4)、线程使用CPU资源期间,执行某个操作进入阻塞状态,如执行读/写操作引起阻塞。进入阻塞状态时线程不能进入线程队列,只有引起阻塞的原因消除时,线程才能进入到线程队列排队等待CPU资源,以便从中断处继续运行。

4、死亡:
死亡状态就是线程释放了实体,即释放了分配给线程对象的内存。线程死亡的原因有两个:
(1)、正常运行的线程完成了它的全部工作,即执行完run()方法中的全部语句,结束了run()方法。
(2)、线程被提前强制性终止,即强制run()方法结束。

线程调度与优先级:
JVM的线程调度器负责管理线程,调度器把线程的优先级分为10个级别,分别用Thread类中的类常量表示。每个Java线程的优先级都在常数1-10之间。Thread类优先级常量有三个:
static int MIN_PRIORITY //1
static int NORM_PRIORITY //5
static int MAX_PRIORITY //10
如果没有明确设置,默认线程优先级为常数5即Thread.NORM_PRIORITY。
线程优先级可以用setPriority(int
grade)方法调整,如果参数grade不在1-10范围内,那么setPriority产生一个IllegalArgumenException异
常。用getPriority()方法返回线程优先级。(注意:有些操作系统只能识别3个级别:1、5、10)

Java调度器的任务
是使优先级高的线程能始终运行,一旦时间片有空闲,则使具有同等优先级的线程以轮流的方式顺序使用时间片。只有当高级别的线程死亡时(除非用
sleep(int millsecond)或wait()方法让出CPU资源),低级别线程才有机会获得CPU资源。

实际编程时,不提倡使用线程的优先级来保证算法的正确执行。要编写正确、跨平台的多线程代码,必须假设线程在任何时刻都有可能被剥夺CPU资源的使用权。