java进程线程
‘壹’ java线程的知识要点
一、进程的概念
进程表示资源分配的基本单位,又是调度运行的基本单位。例如,用户运行自拦念己的程序,系统就创建一个进程,并给它分配资源,包括内存空间、磁盘空间、I/O设备等。然后,把该进程放入就绪队列。进程调度程序选中它,为它分配CPU以及其他有关的资源,该进程才真正运行。简伍困所以,北京电脑培训发现进程是系统中的并发执行的单位。
二、线程的概念
线程:(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
三、引用线程的优势
(1)易于调度。
(2)提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分或相同部分。
(3)开销少。创建线程比创建进程要快,所需开销很少。
(4)利于充分发挥多处理器的功能。通过创建多线程进程(即一个进程可具有两个或更多个线程),每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。
四、进程与线程的关系
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)处理机分给线程,即真正在处理机上运行橘悉的是线程。
(4)线程在执行过程中,要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
简单来说:
1、一个程序至少有一个进程,一个进程至少有一个线程。
2、进程在执行过程中拥有独立的资源,而多个线程共享进程中的资源。
‘贰’ Java多线程程序设计详细解析
一、理解多线程
多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。
线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。
多个线程的执行是并发的,也就是在逻辑上“同时”,而不管是否是物理上的“同时”。如果系统只有一个CPU,那么真正的“同时”是不可能的,但是由于CPU的速度非常快,用户感觉不到其中的区别,因此我们也不用关心它,只需要设想各个线程是同时执行即可。
多线程和传统的单线程在程序设计上最大的区别在于,由于各个线程的控制流彼此独立,使得各个线程之间的代码是乱序执行的,由此带来的线程调度,同步等问题,将在以后探讨。
二、在Java中实现多线凯液慎程
我们不妨设想,为了创建一个新的线程,我们需要做些什么?很显然,我们必须指明这个线程所要执行的代码,而这就是在Java中实现多线程我们所需要做的一切!
真是神奇!Java是如何做到这一点的?通过类!作为一个完全面向对象的语言,Java提供了类java.lang.Thread来方便多线程编程,这个类提供了大量的方法来方便我们控制自己的各个线程,我们以后的讨论都将围绕这个类进行。
那么如何提供给 Java 我们要线程执行的代码呢?让我们来看一看 Thread 类。Thread 类最重要的方法是run(),它为Thread类的方法start()所调用,提供我们的线程所要执行的代码。为了指定我们自己的代码,只需要覆盖它!
方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。下面是一个例子:
public class MyThread extends Thread
{
int count= 1, number;
public MyThread(int num)
{
number = num;
System.out.println
("创建线程 " + number);
}
public void run() {
while(true) {
System.out.println
("线程 " + number + ":计数 " + count);
if(++count== 6) return;
}
}
public static void main(String args[])
{
for(int i = 0;
i 〈 5; i++) new MyThread(i+1).start();
}
}
这种方法简单明了,符合大家的习惯,但是,它也有一个很大的缺点,那就是如果我们的类已经从一个类继承(如小程序必须继承自 Applet 类),则无法再继承 Thread 类,这时如果我们又不想建立一个新的类,应该怎么办呢?
我们不妨来探索一种新的方法:我们不创建Thread类的子类,而是直接使用它,那么我们只能将我们的方法作为参数传递给 Thread 类的实例,有点类似回调函数。但是 Java 没有指针,我们只能传递一个包含这个方法的类的实例。
那么如何限制这个类盯敬必须包含这一方法呢?当然是使用接口!(虽然抽象类也可满足,但是需要继承,而我们之所以要采用这种新方法,不就是为了避免继承带来的限制吗?)
Java 提供了接口 java.lang.Runnable 来支持这种方法。
方法二:实现 Runnable 接口
Runnable接口只有一个方法run(),我们声明自己的类实现Runnable接口并提供这一方法,将我们的线程代码写入其中,就完成了这一部分的任务。但是Runnable接口并没有任何对线程的支持,我们还必须创建Thread类的实例,这一点通过Thread类的构造函数public Thread(Runnable target);来实现。下面埋禅是一个例子:
public class MyThread implements Runnable
{
int count= 1, number;
public MyThread(int num)
{
number = num;
System.out.println("创建线程 " + number);
}
public void run()
{
while(true)
{
System.out.println
("线程 " + number + ":计数 " + count);
if(++count== 6) return;
}
}
public static void main(String args[])
{
for(int i = 0; i 〈 5;
i++) new Thread(new MyThread(i+1)).start();
}
}
严格地说,创建Thread子类的实例也是可行的,但是必须注意的是,该子类必须没有覆盖 Thread 类的 run 方法,否则该线程执行的将是子类的 run 方法,而不是我们用以实现Runnable 接口的类的 run 方法,对此大家不妨试验一下。
使用 Runnable 接口来实现多线程使得我们能够在一个类中包容所有的代码,有利于封装,它的缺点在于,我们只能使用一套代码,若想创建多个线程并使各个线程执行不同的代码,则仍必须额外创建类,如果这样的话,在大多数情况下也许还不如直接用多个类分别继承 Thread 来得紧凑。
综上所述,两种方法各有千秋,大家可以灵活运用。
下面让我们一起来研究一下多线程使用中的一些问题。
三、线程的四种状态
1. 新状态:线程已被创建但尚未执行(start() 尚未被调用)。
2. 可执行状态:线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它执行。
3. 死亡状态:正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果,但是不被推荐,前者会产生异常,后者是强制终止,不会释放锁。
4. 阻塞状态:线程不会被分配 CPU 时间,无法执行。
四、线程的优先级
线程的优先级代表该线程的重要程度,当有多个线程同时处于可执行状态并等待获得 CPU 时间时,线程调度系统根据各个线程的优先级来决定给谁分配 CPU 时间,优先级高的线程有更大的机会获得 CPU 时间,优先级低的线程也不是没有机会,只是机会要小一些罢了。
你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级,线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间,缺省是5(NORM_PRIORITY)。
五、线程的同步
由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。
这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject)
{
//允许访问控制的代码
}
#p#副标题#e#
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
六、线程的阻塞为了解决对共享存储区的访问冲突,Java 引入了同步机制,现在让我们来考察多个线程对共享资源的访问,显然同步机制已经不够了,因为在任意时刻所要求的资源不一定已经准备好了被访问,反过来,同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题,Java 引入了对阻塞机制的支持。
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。
1. sleep() 方法:sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新测试,直到条件满足为止。
2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复。
3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。
4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。
初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。
上述的核心区别导致了一系列的细节上的区别。
首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。
而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。
其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在synchronized 方法或块中当前线程才占有锁,才有锁可以释放。
同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。
wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。
它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。
关于 wait() 和 notify() 方法最后再说明两点:
第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。
第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。
谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。
以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify()方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用中我们应该灵活使用各种方法,以便更好地达到我们的目的。
七、守护线程
守护线程是一类特殊的线程,它和普通线程的区别在于它并不是应用程序的核心部分,当一个应用程序的所有非守护线程终止运行时,即使仍然有守护线程在运行,应用程序也将终止,反之,只要有一个非守护线程在运行,应用程序就不会终止。守护线程一般被用于在后台为其它线程提供服务。
可以通过调用方法 isDaemon() 来判断一个线程是否是守护线程,也可以调用方法 setDaemon() 来将一个线程设为守护线程。
八、线程组
线程组是一个 Java 特有的概念,在 Java 中,线程组是类ThreadGroup 的对象,每个线程都隶属于唯一一个线程组,这个线程组在线程创建时指定并在线程的整个生命期内都不能更改。
你可以通过调用包含 ThreadGroup 类型参数的 Thread 类构造函数来指定线程属的线程组,若没有指定,则线程缺省地隶属于名为 system 的系统线程组。
在 Java 中,除了预建的系统线程组外,所有线程组都必须显式创建。在 Java 中,除系统线程组外的每个线程组又隶属于另一个线程组,你可以在创建线程组时指定其所隶属的线程组,若没有指定,则缺省地隶属于系统线程组。这样,所有线程组组成了一棵以系统线程组为根的树。
Java 允许我们对一个线程组中的所有线程同时进行操作,比如我们可以通过调用线程组的相应方法来设置其中所有线程的优先级,也可以启动或阻塞其中的所有线程。
Java 的线程组机制的另一个重要作用是线程安全。线程组机制允许我们通过分组来区分有不同安全特性的线程,对不同组的线程进行不同的处理,还可以通过线程组的分层结构来支持不对等安全措施的采用。
Java 的 ThreadGroup 类提供了大量的方法来方便我们对线程组树中的每一个线程组以及线程组中的每一个线程进行操作。
九、总结
在本文中,我们讲述了 Java 多线程编程的方方面面,包括创建线程,以及对多个线程进行调度、管理。我们深刻认识到了多线程编程的复杂性,以及线程切换开销带来的多线程程序的低效性,这也促使我们认真地思考一个问题:我们是否需要多线程?何时需要多线程?
多线程的核心在于多个代码块并发执行,本质特点在于各代码块之间的代码是乱序执行的。我们的程序是否需要多线程,就是要看这是否也是它的内在特点。
假如我们的程序根本不要求多个代码块并发执行,那自然不需要使用多线程;假如我们的程序虽然要求多个代码块并发执行,但是却不要求乱序,则我们完全可以用一个循环来简单高效地实现,也不需要使用多线程;只有当它完全符合多线程的特点时,多线程机制对线程间通信和线程管理的强大支持才能有用武之地,这时使用多线程才是值得的。
#p#副标题#e#
‘叁’ Java进程和线程有什么区别
概念】
进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,竞争计算机系统资源的基本单位。
线程:是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。
一个程序由一个或多个进程组成,一个进程由一个或多个线程组成。1
【进程 线程的区别】
1.地址空间:
进程之间是独立的地址空间,但同一进程的线程共享本进程的地址空间。1
2.资源占用
同一进程内的线程共享本进程的资源如内存、I/O、cpu等,但是进程之间的资源是独立的。1
3.健壮性
一个进程崩溃后,在保护模式下不会对其他进程产生影响;
一个线程崩溃整个进程都死掉,所以多进程要比多线程健壮。123
4.执行过程
进程可以独立执行,且每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口。
线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。线程是处理器调度的基本单位,但是进程不是。123
5.并发和资源消耗
两者均可并发执行。
进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。
如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程
‘肆’ java线程是什么
一、操作系统中线程和进程的概念
现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
“同时”执行是人的感觉,在线程之间实际上轮换执行。
二、Java中的线程
在Java中,“线程”指两件不同的事情:
1、java.lang.Thread类的一个实例;
2、线程的执行。
使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。
一个Thread类实例只是一个对象,像Java中的任何其他对象一样,具有变量和方法,生死于堆上。
Java中,每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行着。
一个Java应用总是从main()方法开始运行,mian()方法运行在一个线程内,它被称为主线程。
一旦创建一个新的线程,就产生一个新的调用栈。
线程总体分两类:用户线程和守候线程。
当所有用户线程执行完毕的时候,JVM自动关闭。但是守候线程却不独立于JVM,守候线程一般是由操作系统或者用户自己创建的
‘伍’ Java中,线程是什么意思,多线程又是什么
在计算机中当一个程序运行的时候就会创建至少一个进程,例如当我们运行QQ的时候,系统就会创建进程来处理我们平时的一些操作,当我们打开任务管理器的时候,在进程的列表里面就可以找到QQ.exe的运行程序;
在计算机中处理进程之外还有另一个概念就是线程,线程是存在于进程当中,一个进程可以包含多个线程;当我们的计算机有多核处理器的时候,使用多线程可以加快程序的运算速率;如果一个进程中只有一个线程,当程序遇到一个比较耗时的计算的时候,由于程序是单线程的,那么程序只能等待这个运算结束的时候再继续运行,这样会大大的降低程序的效率;当时用多个线程的时候,在某个线程遇到比较耗时的运算的时候,该线程可以继续自己的运算,但是其他的线程也可以同步进行,这样当耗时的计算结束之后,其他线程也将自己所需要的东西执行完毕,这样就会很大的提高程序执行效率;
在程序运行中对于文件的保存相对于处理器的运算速度来说是很慢的,当我们程序中接收到一个保存文件的信息之后,我们可以创建一个保存文件的线程,在主线程中我们可以继续进行我们的其他运算,这样当文件保存好之后,我们的其他运算也会完成,互不影响;
在Java中我们可以创建一个自己的类继承于Thread类,并且重写run() 方法,当线程启动之后,run()方法里面的操作都在线程中进行处理,而不会影响主线程的信息;
当我们创建好一个自定义线程类之后,我们可以创建这个自定义线程的对象,进行线程的启动;线程须调用start();方法进行启动,这样run()方法里面的内容才会在线程中运行;如果我们不去调用start()方法,那我们只是创建了一个普通的类,即使我们手动调用run()方法,run()方法里面的内容也不会在线程中运行;
在Java中线程主要有初始状态,运行状态,阻塞状态,终止状态等;当我们新创建一个线程对象的时候,此时线程的状态为初始状态;当我们调用start()之后,此时的线程才被激活成为运行状态,之后run()方法里面的信息才会在子线程中运行;我们可以在不同的阶段调用不同的方法将线程设置为不同的状态;比如有时候我们的操作需要等待其他线程中运算结束之后才可以继续进行,这时候我们就可以将线程设置为等待状态,当需要的资源满足条件之后,可以继续运行当前的线程;
以上的内容就是关于Java中线程是什么,更多关于Java方面的问题可以看下这个视频教程:网页链接,希望我的回答能帮到你。
‘陆’ java 中线程是什么东东
线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。
线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程.
线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文.多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定. 线程的运行中需要使用计算机的内存资源和CPU
‘柒’ java中什么叫做线程什么叫多线程多线程的特点是什么
在 Java 中,线程(Thread)是指程序执行的一条路径,是进程中的一个实体。Java 中的线程是轻量级的,可以同时运行多个线程,这就是多线程(Multithreading)。
多线程是指在一个程序中同时运行多个线程,每个线程都可以独立执行不同的任务。多线程的特点包括:
提高程序的并发性:多线程可以让程序同时执行多个任务,提高程序的并发性,从而提高程序的效率。
提旅凯毁高程序的响应性:多线程可以让程序拆备在执行耗时操作时不会阻塞,从孙隐而提高程序的响应性,使用户能够更快地得到反馈。
充分利用 CPU 资源:多线程可以让程序充分利用 CPU 资源,提高 CPU 的利用率,从而提高程序的效率。
方便处理复杂的任务:多线程可以让程序同时处理多个复杂的任务,从而方便处理复杂的任务。
需要注意的是,多线程也会带来一些问题,例如线程安全问题、死锁问题等,因此在编写多线程程序时需要注意这些问题。
‘捌’ java 中线程与进程的区别是什么
进程,是针对于操作系统而言的
线程,是java中一个重要的类,主要用来多个方法一起执行
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
‘玖’ Java线程的概念与原理
一 操作系统中线程和进程的概念
兄缺现在的操作系统是多任务操作系统 多线程是实现多任务的一种方式
进程是指一个内存中运行的应用程序 每个进程都有自己独立的一块内存空间 一个进程中可以启动多个线程 比如在Windows系统中 一个运行的exe就是一个进程 线程是指进程中的一个执行流程 一个进程中可以运行多个线程 比如java exe进程中可以运行很多线程 线程总是属于某羡毕辩个进程 进程中的多个线程共享进程的内存 同时 执行是人的感觉 在线程之间实际上轮换执行
二 Java中的线程
在Java中 线程 指两件不同的事情
java lang Thread类的一个实例
线程的执行
使用java lang Thread类或者java lang Runnable接口编写代码来定义 实例化和启动新线程 一个Thread类实例只是一个对象 像Java中的任何其他对象一样 具有变量和方法 生死于堆上 Java中 每个线程都有一个调用栈 即使不在程序中创建任何新的线程 线程也在后台运行着 一个Java应用总是从main()方法开始运行 mian()方法运行在一个线程内 它被称为主线程 一旦创建一个新的线程 就产生一个新的调用栈 线程总体分两类 用户线程和守候线程
当所有用户线程执行完毕的时候 JVM自动关闭 但是守候线程却不独立于JVM 守候线程一般是由操作系统或者用户自己创建的
———————————MultiT java——————————————————————
class MultiThread
{
public static void main(String[] args)
{
MyThread mt=new MyThread();
//mt setDaemon(true);//设定为后台线程 main进程结束时 后台进程也跟着结束
//mt setPriority(Thread MAX_PRIORITY); //设定线程优先级 MAX_PRIORITY为 MIN_PRIORITY为 NORM_PRIORITY为
//设定为最高优先级后 程序运行时 mt线程一直运行 强制终止时 main线程才运行
//设定为最高优先级的线程 无论有无yield(); 线程总一直运行 直到强制终止时 main和mt线程交替运行
mt start();
int index= ;
while(true) //显示结果与教程不同
{
if(index++== )
break;
System out println( main: +Thread currentThread() getName()); //获取线程名字
}
}
}
class MyThread extends Thread
{
public void run()
{
while(true)
{
System out println(getName());
yield(); //允许当前线程停止 转去执行其他线程 静态方法
//mt进程执行时 切换到main进程 main进程执行一段时间数帆后
//切换进程到mt mt执行完获取名字后 返回到main进程
}
}
}
//一个长时间处于等待状态的线程也有可能被线程调度器调度 从而运行
//打破高优先级线程始终获有运行时间的状态
——————————————————————————————————————
——————————MultiThread java———————————————————————
class MultiThread
{
public static void main(String[] args)
{
MyThread mt=new MyThread();
//new Thread(mt) start(); //创建多个同样的线程访问同一个变量index 若MyThread采用继承Thread方式 则无法共享同一个变量
//new Thread(mt) start();
//new Thread(mt) start();
//new Thread(mt) start();
mt getThread() start(); //也可以采用内部类的方式共享访问同一个变量
mt getThread() start();
mt getThread() start();
mt getThread() start();
//mt setDaemon(true);//设定为后台线程 main进程结束时 后台进程也跟着结束
//mt setPriority(Thread MAX_PRIORITY); //设定线程优先级 MAX_PRIORITY为 MIN_PRIORITY为 NORM_PRIORITY为
//设定为最高优先级后 程序运行时 mt线程一直运行 强制终止时 main线程才运行
//设定为最高优先级的线程 无论有无yield(); 线程总一直运行 直到强制终止时 main和mt线程交替运行
//mt start();
int index= ;
while(true) //显示结果与教程不同
{
// if(index++== )
// break;
System out println( main: +Thread currentThread() getName()); //获取线程名字
}
}
}
class MyThread //implements Runnable //extends Thread //使用外部类的方式
//使用内部类完成使用Runnable接口才能完成的两个功能 a 创建多个线程 b 访问同一个变量
{
int index= ;
private class InnerThread extends Thread //不想让外部访问其实现方法 加上private
{
public void run()
{
while(true)
{
System out println(Thread currentThread() getName()+ : +index++);
}
}
}
Thread getThread()
{
return new InnerThread();
}
/*
public void run()
{
while(true)
{
System out println(Thread currentThread() getName()+ : +index++);
//yield(); //允许当前线程停止 转去执行其他线程 静态方法
//mt进程执行时 切换到main进程 main进程执行一段时间后
//切换进程到mt mt执行完获取名字后 返回到main进程
}
}
*/
}
//一个长时间处于等待状态的线程也有可能被线程调度器调度 从而运行
//打破高优先级线程始终获有运行时间的状态
//如果不需要修改Thread类的除了run方法外的其他方法 选用implements Runnable
———————————————————————————————————————
———————————TicketsSystem java———————————————————
//多线程实现火车票的售票系统 用同步块 或着同步方法
class TicketsSystem
{
public static void main(String[] args) //运行结果与教程中不同 不完全顺序 每次运行 顺序都不完全一样
{
SellThread st=new SellThread();//创建四个线程访问同一变量tickets
// 错 SellThread st =new SellThread();//若采用创建四个对象的方式 则每个对象中都有 张票
new Thread(st) start(); //b为false 用的同步方法 | //同步方法与同步块共用中 显示的是只调用了同步块 而同步方法未被调用
//b为true 用的同步块 | //原因 启动第一个线程后 CPU时间片没有到期 线程没有立即运行 接着执行b=true
// | //解决办法 启动第一个线程后 执行一个睡眠时间 让CPU时间片到期
try
{
Thread sleep( );
}
catch(Exception e)
{
e printStackTrace();
}
st b=true;
new Thread(st) start();
//new Thread(st) start();
//new Thread(st) start();
}
}
class SellThread implements Runnable //程序有点小问题 当剩下最后一张票时 四个线程都运行 可能会出现票数为 (系统长时间运行时)
//可加上一个静态方法sleep();它会抛出异常
{
int tickets= ;
//Object obj=new Object();//也可以声明一个Thread对象
Thread th=new Thread();
boolean b=false;
public void run()
{
if(b==false)
{
while(true)
sell();
}
else
{
while(true)
{ //同步方法利用的是this所代表的对象的锁
synchronized(this) //采用同步后 显示正确 此方法两步 声明Thread对象 用synchronized把原方法括起来
{ //这里换th为this
///*
if(tickets> )
{
try
{
Thread sleep( );
}
catch(Exception e)
{
e printStackTrace();
}
System out println( th +Thread currentThread() getName()+ sell tickets: +tickets);
tickets ;
}
//*/
}
}
}
}
public synchronized void sell() //每个class也有一个锁 是这个class所对应的class对象的锁(监视器)
{
if(tickets> )
{
try
{
Thread sleep( );
}
catch(Exception e)
{
e printStackTrace();
}
System out println( sell +Thread currentThread() getName()+ sell tickets: +tickets);
tickets ;
}
}
}
————————————————————————————————————————
———————————TestWN java————————————————————
class Test
{
public static void main(String[] args)
{
Queue q=new Queue();
Procer p=new Procer(q);
Consumer c=new Consumer(q);
p start();
c start();
}
}
class Procer extends Thread
{
Queue q;
Procer(Queue q)
{
this q=q;
}
public void run()
{
for(int i= ;i< ;i++)
{
q put(i);
System out println( Procer put: +i);
}
}
}
class Consumer extends Thread
{
Queue q;
Consumer(Queue q)
{
this q=q;
}
public void run()
{
while(true)
{
System out println( Consumer get: +q get());
}
}
}
class Queue //wait notify 方法必须用在同步方法中 要加上关键字synchronized
{
int value;
boolean bFull=false;
public synchronized void put(int i)
{
if(!bFull)
{
value=i;
bFull=true;
notify();
}
try
{
wait();
}
catch(Exception e)
{
e printStackTrace();
}
}
public synchronized int get()
{
if(!bFull)
{
try
{
wait();
}
catch(Exception e)
{
e printStackTrace();
}
}
bFull=false;
notify();
return value;
}
}
————————————————————————————————————
————————————TestThread java———————————————————————
class TestThread
{
public static void main(String[] args)
{
Thread t =new Thread ();
t start();
int index= ;
while(true)
{
if(index++== )
{
t stopThread();
t interrupt(); //让线程 终止
break;
}
System out println(Thread currentThread() getName());
}
System out println( main() exit );
}
}
class Thread extends Thread
{
private boolean bStop=false;
public synchronized void run()
{
while(!bStop)
{
try
{
wait(); //加入wait后 main线程结束时 程序还未终止 原因是Thread 的线程调用wait方法 进入对象的等待队列中 需要notify方法将它唤醒
}
catch(Exception e)
{
//e printStackTrace();
if(bStop)
return;
}
System out println(getName());
}
}
public void stopThread()
{
bStop=true;
}
}
lishixin/Article/program/Java/gj/201311/27407