一般来说,我们把正在计算机中执行的程序叫做"进程"(Process) ,而不将其称为程序(Program)。
所谓"线程"(Thread),是"进程"中某个单一顺序的控制流。新兴的操作系统,如Mac,Windows NT,Windows 95等,大多采用多线程的概念,把线 程视为基本执行单位。
线程也是Java中的相当重要的组成部分之一。 甚至最简单的Applet也是由多个线程来完成的。
在Java中, 任何一个Applet的paint()和update()方法都是由AWT(Abstract Window Toolkit)绘图与事件处理线程调用的,而Applet 主要的里程碑方法——init(),start(),stop()和destory() ——是由执行该Applet的应用调用的。 单线程的概念没有什么新的地方,真正有趣的是在一个程序中同时使用多个线程来完成不同的任务。
某些地方用轻量进程(Lightweig ht Process)来代替线程,线程与真正进程的相似性在于它们都是单一顺序控制流。然而线程被认为轻量是由于它运行于整个程序的上下文内,能使用整个程序共有的资源和程序环境。
作为单一顺序控制流,在运行的程序内线程必须拥有一些资源作为必要的开销。例如,必须有执行堆栈和程序计数器在线程内执行的代码只在它的上下文中起作用,因此某些地方用"执行上下文"来代替"线程"。
线程属性 为了正确有效地使用线程,必须理解线程的各个方面并了解Java 实时系统。 必须知道如何提供线程体、线程的生命周期、实时系统如何调度线程、线程组、什么是幽灵线程(Demo nThread)。
Java多线程程序需要我们具体的学习相关语法。
其中我们要了解相关的语法究竟有什么。很多重要的问题成本都在细节,基本的语法就是Java多线程程序的细节。
希望大家有所收获。 Java多线程程序中经常用到的方法有以下几个:run(),start(),wait(),sleep(),notify(),notifyAll(),yield(),join(),还有一个重要的关键字 synchronized。
下面分别对这些方法进行解释: run()和start() 这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由Java的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。
关键字Synchronized 这个关键字用于保护共享数据,当然前提是要分清哪些数据是共享数据。每个对象都有一个锁标志,当一个线程访问该对象时,被Synchronized修饰的数据将被“上锁”,阻止其他线程访问。
当前线程访问完这部分数据后释放锁标志,其他线程就可以访问了。 1。
public ThreadTest implements Runnable 2。{ 3。
public synchronized void run(){ 4。for(int i=0;i out。
println(" " + i); 7。} 8。
} 9。public static void main(String[] args) 10。
{ 11。Runnable r1 = new ThreadTest(); 12。
Runnable r2 = new ThreadTest(); 13。 Thread t1 = new Thread(r1); 14。
Thread t2 = new Thread(r2); 15。t1。
start(); 16。t2。
start(); 17。} 18。
} 以上这段程序中的 i 变量并不是共享数据,也就是这里的Synchronized关键字并未起作用。 因为t1,t2两个线程是两个对象(r1,r2)的线程。
不同的对象其数据是不同的,所以r1和r2两个对象的i变量是并不是共享数据。 当把代码改成如下:Synchronized关键字才会起作用 19。
Runnable r = new ThreadTest(); 20。 Thread t1 = new Thread(r); 21。
Thread t2 = new Thread(r); 22。t1。
start(); 23。t2。
start(); 以上就是对Java多线程程序的详细介绍。
为什么会排队等待? 下面的这个简单的 Java 程序完成四项不相关的任务。
这样的程序有单个控制线程,控制在这四个任务之间线性地移动。此外,因为所需的资源 — 打印机、磁盘、数据库和显示屏 -- 由于硬件和软件的限制都有内在的潜伏时间,所以每项任务都包含明显的等待时间。
因此,程序在访问数据库之前必须等待打印机完成打印文件的任务,等等。如果您正在等待程序的完成,则这是对计算资源和您的时间的一种拙劣使用。
改进此程序的一种方法是使它成为多线程的。 在本例中,每项任务在开始之前必须等待前一项任务完成,即使所涉及的任务毫不相关也是这样。
但是,在现实生活中,我们经常使用多线程模型。我们在处理某些任务的同时也可以让孩子、配偶和父母完成别的任务。
例如,我在写信的同时可能打发我的儿子去邮局买邮票。用软件术语来说,这称为多个控制(或执行)线程。
限制线程优先级和调度 Java 线程模型涉及可以动态更改的线程优先级。
本质上,线程的优先级是从 1 到 10 之间的一个数字,数字越大表明任务越紧急。JVM 标准首先调用优先级较高的线程,然后才调用优先级较低的线程。
但是,该标准对具有相同优先级的线程的处理是随机的。 如何处理这些线程取决于基层的操作系统策略。
在某些情况下,优先级相同的线程分时运行;在另一些情况下,线程将一直运行到结束。请记住,Java 支持 10 个优先级,基层操作系统支持的优先级可能要少得多,这样会造成一些混乱。
因此,只能将优先级作为一种很粗略的工具使用。 最后的控制可以通过明智地使用 yield() 函数来完成。
通常情况下,请不要依靠线程优先级来控制线程的状态。 小结 本文说明了在 Java 程序中如何使用线程。
像是否应该使用线程这样的更重要的问题在很大程序上取决于手头的应用程序。决定是否在应用程序中使用多线程的一种方法是,估计可以并行运行的代码量。
并记住以下几点: 使用多线程不会增加 CPU 的能力。但是如果使用 JVM 的本地线程实现,则不同的线程可以在不同的处理器上同时运行(在多 CPU 的机器中),从而使多 CPU 机器得到充分利用。
如果应用程序是计算密集型的,并受 CPU 功能的制约,则只有多 CPU 机器能够从更多的线程中受益。 当应用程序必须等待缓慢的资源(如网络连接或数据库连接)时,或者当应用程序是非交互式的时,多线程通常是有利的。
基于 Internet 的软件有必要是多线程的;否则,用户将感觉应用程序反映迟钝。例如,当开发要支持大量客户机的服务器时,多线程可以使编程较为容易。
在这种情况下,每个线程可以为不同的客户或客户组服务,从而缩短了响应时间。 某些程序员可能在 C 和其他语言中使用过线程,在那些语言中对线程没有语言支持。
这些程序员可能通常都被搞得对线程失去了信心。
一、主内存与工作内存 1。
Java 内存模型的主要目标是定义程序中各个变量的访问规则。此处的变量与Java编程时所说的变量不一样,指包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为它们是线程私有的,不会被共享。
2。Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的虚拟内存。
线程的虚拟内存中保存了该线程使用到的变量到主内存副本拷贝。线程对变量的所有操作(读取、赋值)都必须在自己的虚拟内存中进行,而不能直接读写主内存中的变量。
不同线程之间无法直接访问对方虚拟内存中的变量,线程间变量值的传递均需要在主内存来完成。 二、内存间交互操作 关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步到主内存之间的实现细节,Java内存模型定义了以下八种操作来完成: ? lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
? unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后 的变量才可以被其他线程锁定。 。
线程是Java语言的一个部分,而且是Java的最强大的功能之一。
究竟什么是线程,为什么要开发基于线程的应用程序?在本文中,我们将深入了解一下线程的用法,以及使用线程的一些技术。在我们开始讲述线程之前,最好先了解一下有关背景知识和分析一下线程的工作原理。
当程序员一开始开发应用程序时,这些应用程序只能在一个时间内完成一件事情。应用程序从主程序开始执行,直到运行结束,像 Fortran/Cobol/Basic这些语言均是如此。
随着时间的推移,计算机发展到可以在同一时间段内运行不止一个应用程序的时代了,但是应用程序运行时仍然是串行的,即从开始运行到结束,下一条指令接着上一条指令执行。 到最近,程序发展到可以在执行时,以若干个线程的形式运行。
Java就具有运行多线程的能力,可以在同一时间段内进行几个操作,这就意味着给定的操作不必等到另外一个操作结束之后,才能开始。而且对某个操作可以指定更高一级的优先级。
不少程序语言,包括ADA, Modula-2和C/C++,已经可以提供对线程的支持。 同这些语言相比,Java的特点是从最底层开始就对线程提供支持。
除此以外,标准的Java类是可重入的,允许在一个给定的应用程序中由多个线程调用同一方法,而线程彼此之间又互不干扰。Java的这些特点为多线程应用程序的设计奠定了基础。
什么是线程?究竟什么是线程呢?正如在图A中所示,一个线程是给定的指令的序列 (你所编写的代码),一个栈(在给定的方法中定义的变量),以及一些共享数据(类一级的变量)。 线程也可以从全局类中访问静态数据。
进程是程序在处理机中的一次运行。
一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立。所以进程是重量级的任务,它们之间的通信和转换都需要操作系统付出较大的开销。
线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程自己基本上不拥有系统资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。
所以线程是轻量级的任务,它们之间的通信和转换只需要较小的系统开销。 Java支持多线程编程,因此用Java编写的应用程序可以同时执行多个任务。
Java的多线程机制使用起来非常方便,用户只需关注程序细节的实现,而不用担心后台的多任务系统。 Java语言里,线程表现为线程类。
Thread线程类封装了所有需要的线程操作控制。在设计程序时,必须很清晰地区分开线程对象和运行线程,可以将线程对象看作是运行线程的控制面板。
在线程对象里有很多方法来控制一个线程是否运行,睡眠,挂起或停止。线程类是控制线程行为的唯一的手段。
一旦一个Java程序启动后,就已经有一个线程在运行。可通过调用Thread.currentThread方法来查看当前运行的是哪一个线程。
class ThreadTest{ public static void main(String args[]){ Thread t = Thread.currentThread(); t.setName("单线程"); //对线程取名为"单线程" t.setPriority(8); //设置线程优先级为8,最高为10,最低为1,默认为5 System.out.println("The running thread: " + t); // 显示线程信息 try{ for(int i=0;i<3;i++){ System.out.println("Sleep time " + i); Thread.sleep(100); // 睡眠100毫秒 } }catch(InterruptedException e){// 捕获异常 System.out.println("thread has wrong"); } } } 多线程的实现方法 继承Thread类 可通过继承Thread类并重写其中的run()方法来定义线程体以实现线程的具体行为,然后创建该子类的对象以创建线程。在继承Thread类的子类ThreadSubclassName中重写run()方法来定义线程体的一般格式为: public class ThreadSubclassName extends Thread{ public ThreadSubclassName(){ 。
.. // 编写子类的构造方法,可缺省 } public void run(){ 。.. // 编写自己的线程代码 } } 用定义的线程子类ThreadSubclassName创建线程对象的一般格式为: ThreadSubclassName ThreadObject = new ThreadSubclassName(); 然后,就可启动该线程对象表示的线程: ThreadObject.start(); //启动线程 应用继承类Thread的方法实现多线程的程序。
本程序创建了三个单独的线程,它们分别打印自己的“Hello World!”。 class ThreadDemo extends Thread{ private String whoami; private int delay; public ThreadDemo(String s,int d){ whoami=s; delay=d; } public void run(){ try{ sleep(delay); }catch(InterruptedException e){ } System.out.println("Hello World!" + whoami + " " + delay); } } public class MultiThread{ public static void main(String args[]){ ThreadDemo t1,t2,t3; t1 = new ThreadDemo("Thread1", (int)(Math.random()*2000)); t2 = new ThreadDemo("Thread2", (int)(Math.random()*2000)); t3 = new ThreadDemo("Thread3", (int)(Math.random()*2000)); t1.start(); t2.start(); t3.start(); } } 实现Runnable接口 编写多线程程序的另一种的方法是实现Runnable接口。
在一个类中实现Runnable接口(以后称实现Runnable接口的类为Runnable类),并在该类中定义run()方法,然后用带有Runnable参数的Thread类构造方法创建线程。创建线程对象可用下面的两个步骤来完成:(1)生成Runnable类ClassName的对象 ClassName RunnableObject = new ClassName();(2)用带有Runnable参数的Thread类构造方法创建线程对象。
新创建的线程的指针将指向Runnable类的实例。用该Runnable类的实例为线程提供 run()方法---线程体。
Thread ThreadObject = new Thread(RunnableObject); 然后,就可启动线程对象ThreadObject表示的线程:ThreadObject.start(); 在Thread类中带有Runnable接口的构造方法有: public Thread(Runnable target); public Thread(Runnable target, String name); public Thread(String name); public Thread(ThreadGroup group,Runnable target); public Thread(ThreadGroup group,Runnable target, String name); 其中,参数Runnable target表示该线程执行时运行target的run()方法,String name以指定名字构造线程,ThreadGroup group表示创建线程组。用Runnable接口实现的多线程。
class TwoThread implements Runnable{ TwoThread(){ Thread t1 = Thread.currentThread(); t1.setName("第一主线程"); System.out.println("正在运行的线程: " + t1); Thread t2 = new Thread(this,"第二线程"); System.out.println("创建第二线程"); t2.start(); try{ System.out.println("第一线程休眠"); Thread.sleep(3000); }catch(InterruptedException e){ System.out.println("第一线程有错"); } System.out.println("第一线程退出"); } public void run(){ try{ for(int i = 0;i < 5;i++){ System.out.println(“第二线程的。
声明:本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
蜀ICP备2020033479号-4 Copyright © 2016 学习鸟. 页面生成时间:3.112秒