操作系统级别的进程与线程
进程
一个计算机程序的运行实例。包含了需要执行的指令,有自己的独立地址空间,是互相隔离的。进程拥有各种资源和状态信息,包括打开的文件、子进程和信号处理。
线程
表示程序的执行流程,是CPU调度执行的基本单位。线程有自己的程序计数器、相同的地址空间、同时共享进程所拥有的内存和其他资源。
Java中的并发编程简介
并发编程的优点:
并发编程可以使程序执行速度得到极大提高,或者为设计某些类型的程序提供更易用的模型。
Java中并发的常用之处:
Web应用是最常见的Java系统之一,而基本的Web库类、Servlet具有天生的多线程性。此外,图形化用户界面Swing和SWT类库都拥有针对线程安全的机制,要熟练的掌握仍然需要理解并发。
Java线程机制简介:
Java线程机制是抢占式(非协作式)的,这意味着调度机制会周期性地中断线程,将上下文切换到另一个线程。
Java中的简单线程编程实现
java中实现最简单的线程编程
定义任务
要想定义任务,则需要实现Runnable接口并编写run( )方法,使得该任务可以执行自己的想法。
注: 要想从Runnable导出一个类,则这个类必须有run( )方法
实现Runnable接口只是定义一个任务,该类并没有任何内在的线程能力
下面的实例中,我们在主方法中实例化MainTask类来在主线程(分配给main的那个线程)中调用此任务。
驱动任务
经过上面对 定义任务
的了解,相信大家已经对于如何在java中创建任务有了了解。但是单单定义任务并不能满足我们的需要。我们的目的是将定义的Runnable对象转变为工作任务。
要想驱动任务,则需要将这个Runnable对象提交给一个Thread构造器。
Thread类的最基本方法:
- Thread.start( )方法:该方法为该线程(即将执行构造器中的任务的线程)执行必需的初始化操作,然后调用Runnable的run( )方法,从而在这个新线程中启动该任务。
- Thread.sleep( int )方法:该方法的参数为以毫秒(ms)为单位,意在中止当前线程执行的任务指定的时间。但是该写法已经过时,目前Java SE(5/6及以上)新写法为 TimeUnit.MILLISECONDS.sleep( int )
-Thread.yield( )方法:该方法的调用是对线程调度器的一种建议。这一方法的调用意在声明该进程中正在执行的任务已经完成了生命周期中最重要的部分了,此刻将时间片分给其他任务使用会造成比较小的额外开销。
有关于更多关于Thread类的方法的在后续文章中会逐步介绍。
下面这个例子展示了如何通过Thread类来驱动任务
下面这个例子显示了如何创建多个线程,同时驱动多个任务(由于输出过多,样例输出省略了一部分)
管理多个Thread
之前我们接触的例子都是只有一个任务,并由一个Thread对象驱动的简单例子。但往往在我们的实际编程中,会有好多时候需要多个Thread对象驱动任务,这里我们引进Java SE5的java.util.concurrent包中的Executor(执行器)类。Executor类将为我们管理Thread对象,从而简化并发编程。
下面是一个简单的使用Executor的例子:
注:
- 在例子中我们创建的是一个ExecutorService对象,该对象是使用静态的Executor方法创建的。在这里同样你可能还注意到了我们在初始化Executor对象的时候用的方法是Executors类的 newCachedThreadPool( )方法,这里我们同样还可以调用其他的方法 对ExecutorService对象进行初始化,例如newFixedThreadPool( )方法。
`二者区别`:CachedThreadPool将为每个任务都创建一个线程。而利用FixedThreadPool,可以一次性预先执行代价高昂的线程分配,因而也就可以限制线程的数 量了(相比CachedThreadPool,可以节省每次创建线程的开销)。
- ExecutorService对象是使用静态的Executor方法创建的,这个方法可以确定其Executor类型
总结
有了以上的理解,应该对基本的任务以及线程的概念有了一些基本概念。但这仅仅是一个开始,在下一篇博文中,将继续介绍有关线程的知识(重点是对线程的异常问题及共享受限资源的解释)。
参考书籍:《Java编程思想》