Java并发编程实战--简介

 Java并发编程实战--简介

       导读:在Java编程中,编写正确的并发编程本身就是一件难事,与串行程序相比,并发程序很容易出错。在Java中如何编写Java并行的编程呢--线程。线程可以使复杂的程序变得简单,简化复杂程序的系统开发。处理器的增多,高效的使用并发变得尤为重要。

     一、简介

1.1并发简史

     在最初的计算机中,计算机只有一个主线程(原因是没有操作系统),运行所有的程序都是这样,在这样的环境之下,系统运行不仅受到了限制,而且对于计算机本事来说,更是一种资源的浪费。

    操作系统的出现,使现在的电脑开始拥有了多线程,多个程序之间相互独立。操作系统为多个正在执行的进程进行独立分配,,其中包括内存、文件句柄、安全证书。如果需要的话,不同的进程之间,会有一些粗粒度的通信机制来交换数据,如:套接字、信号处理器、共享内存、信号量、文件。

    计算机中加入操作系统实现多个程序同时执行,目的:

    资源利用率--当程序同时进行两个时,必须进行一个等待另外一个,多线程无疑解决了这个问题。

    公平性--不同的用户和程序对于计算机上的资源拥有这相同的使用权利,一种高效的运行方式,是通过粗粒度的时间分片使这些用户和程序共享计算机资源,不是一个程序从开始到结束,然后再启动下一个程序。

    便利性--编写多个程序,在执行一个任务的时候可以互相通信。

    线程,也被成为轻量级进程,如果没有明确的协同机制,那么线程,将彼此独立执行。由于同一个进程中,所有的线程都将共享同一个进程的内存空间,因此这些线程都将在同一个堆上分配对象。这就需要实现一种比进程间共享数据粒度数据更细的    数据共享机制。如果没有明确的同步机制协同对数据的访问,那么当一个线程正在使用一个变量的时候,另一个线程可能同时访问这个变量,这就是一个非常有必要解决的问题。

1.2线程的优势

A. 有效的降低程序的开发和维护成本,提高复杂应用程序性能。

B. 线程可以将大部分的异步工作流转换成串行工作流,模拟人类的工作方式和交互方式。

C. 降低代码复杂度。

D. 在服务器应用程序中,提升资源利用率以及系统吞吐量,简化JVM实现--因为JVM实现用到了专门的线程。

1.2.1  发挥多处理器的强大性能

    由于基本的调度单位是线程,如果程序中只有一个线程,则最多在一个处理器上运行。在双处理器系统上,单线程的程序只能使用一半的系统资源,那么若是在一百核处理器,99%资源将无法使用。程序设计正确,就可以节省资源,提高利用率。

    同时,多线程可以同时完成多个状态例如同步I/O流操作时,另外一个可以继续运行。

1.2.2建模的简单性

     如果为模型中每一个任务都分配一个线程,那么可能形成一种串行执行的假象。通过使用线程,可以将复杂并且异步的工作流进一步分解为简单而且同步的工作流,每一个工作流在一个单独的线程中运行,并在特定的同步位置交换。

    我们可以使用一些特定的框架来实现这一些细节,例如:servlet和RMI(远程方法调用),他们可以实现细节如线程创建、请求管理、负载均衡,并在正确的时刻将请求分配给正确的应用组件。编写servlet的编程人员不需要知道同一时刻有多少请求被处理,也不需要了解套接字的输入流或输出流是否被阻塞。当调用servlet的service方法请求Web时可以以同步方式来处理这个请求,就好像是一个单线程程序。

1.2.3异步事件的简化处理

服务器在接受多个远程客户端套接字请求时,为每个链接都分配了其各自线程,并且使用同步I/O,则降低这类程序的开发难度。如果程序对套接字的执行读操作还没有来到,读操作则一直被阻塞,直到数据到达。在单线程中,这不仅意味着处理请求的过程中将停顿,而且还意味着在线程被阻塞期间,所有请求的处理将被停顿。处理这一类问题,在单线程中必须使用非阻塞I/O,而非阻塞I/O的复杂度远远高于阻塞I/O,容易出错。

     现在的操作系统,线程的数量已经得到很大的提升,在很多的客户端,每一个分配一个线程,也是可行的。

1.2.4响应更灵敏的用户界面

     在现在的GUI框架中例如AWT和Swing框架,采用了事件分发线程。当某个用户界面事件发生时,在事件线程中,将调用应用程序的事件处理器。由于大多数的GUI框架都是单线程子系统,因此目前为止,任然存在主事件循环,但现在在GUI 控制下并在自己的线程中运行,而不是在应用程序的控制下。

1.3线程带来的风险

      Java对多线程的支持其实是一把双刃剑,Java提供了相应的语言和库,以及明确的跨平台内存模型--该模型实现了Java来发“编写一次随处运行”并发应用模型,简化了开发,提高了编程人员的要求。

 1.3.1  安全性问题

首先我们看一段代码:



在图中可以看到,如果两个线程同时访问方法getNext,就会得到相同的值。

解决办法:那么我们就可以将这个方法改为一个同步的方法。


如果没有同步,那么无论是编辑器,硬件还是运行时,都可以随意安排操作的执行时间和顺序,例如寄存器或处理器变量进行缓存,这些缓存的变量相对于其他线程来说暂时(甚至)永久是不可见的。虽然这些技术有助于实现跟优秀的性能,并且也是只得采用的方法,但也会带来负担,需要知道哪一些会被多个线程共享。不破坏线程安全性。

1.3.2线程活泼性

例如线程A等待线程B释放其特有资源,然而线程B 却一直不释放,那么A将永远等待下去。在以后的文章中会解释这样的事情如何避免。

不懂在下面留言即可

欢迎订阅关注公众号(JAVA和人工智能)

                                       

                                                           获取更多免费书籍、资源、视频资料


                                    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JAVA和人工智能

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值