JAVA学习笔记(三十二)
认识多线程
1.1 进程与线程
dos系统有一个非常明显的缺点,只要一中病毒之后系统会立刻死
机,因为传统的dos系统采用单进程的处理方式,所以只能有一个
程序独自运行,其他程序无法运行。
windows采用的事多进程的处理方式,在同一时间段同时运行多个
程序。
线程实际上就是在进程基础上的进一步划分。当然,会同时存在多
个线程。
如果一个进程没有了,则线程肯定会消失;
如果线程消失了,进程未必消失。
所有的线程都是在进程的基础上并发执行的。
进程是程序的一次动态执行过程,它经历了从代码加载,执行到执
行完毕的一个完整过程,这个过程也是进程本身从产生到最终消亡
的过程。
多线程是实现并发机制的一种有效手段。二者都是并发执行的一个
基本单位。
如果现在同时运行多个任务,则所有的系统资源都是共享的,被所
有线程所共有,但是程序处理需要CPU,传统的单核CPu,在同一个
时间段上会有多个程序执行,但是在同一时间点上只能存在一个程
序运行,也就是说,所有的程序都要抢占CPU资源。
但是现在的CPU已经发展到多核的状态了,在一个电脑上可能会存
在多个cpu。
1.2 java的多线程实现
在java中实现多线程的方式有两种:
:继承THread类
:实现Runnable接口
1.3
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行
多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线
程。每个线程都可以或不可以标记为一个守护程序。当某个线程中
运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被
设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,
新线程才是守护程序。
当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调
用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直
到下列任一情况出现时为止:
调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作
发生。
非守护线程的所有线程都已停止运行,无论是通过从对 run 方法
的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。
创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子
类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启
动该子类的实例。例如,计算大于某一规定值的质数的线程可以写
成:
----------------------------------------------------------
----------------------
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
----------------------------------------------------------
----------------------
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143);
p.start();
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然
后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时
作为一个参数来传递并启动。采用这种风格的同一个例子如下所示
:
----------------------------------------------------------
----------------------
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
----------------------------------------------------------
----------------------
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
每个线程都有一个标识名,多个线程可以同名。如果线程创建时
没有指定标识名,就会为其生成一个新名称。
从以下版本开始:
JDK1.0
1.4 A:THread类
THread类是在java.lang包中定义的,java.lang.Thread
,java.lang包会在程序运行时自动导入,所以无需手工编写imprt
语句。
一个类继承了Thread类之后,那么此类就具备了多线程的操作功能
在THread类中必须明确的覆写THread类中的run()方法 ,此方法
为线程的主体。
多线程的定义:
class 类名称 extends THread{
属性:
方法:
public void run()
{
线程主体;
}
}
class MyThread extends Thread
{
private String name;
public MyThread(String name){
this.name = name;
}
public void run(){
for( int i = 0;i < 10;i ++){
System.out.println(name+"运行:i="+i);
}
}
};
public class ThreadDemo01
{
public static void main(String args[]){
MyThread th1 = new MyThread("线程A:");
MyThread th2 = new MyThread("线程B:");
th1.run();
th2.run();
}
}
结果:
F:\java\thread>java ThreadDemo01
线程A:运行:i=0
线程A:运行:i=1
线程A:运行:i=2
线程A:运行:i=3
线程A:运行:i=4
线程A:运行:i=5
线程A:运行:i=6
线程A:运行:i=7
线程A:运行:i=8
线程A:运行:i=9
线程B:运行:i=0
线程B:运行:i=1
线程B:运行:i=2
线程B:运行:i=3
线程B:运行:i=4
线程B:运行:i=5
线程B:运行:i=6
线程B:运行:i=7
线程B:运行:i=8
线程B:运行:i=9
问题:以上的程序是先执行A后在执行B,并没有并发执行;
因为以上的程序还是按照古老的形式调用的,但是如果要启动一个
线程,必须使用thread类中定义的srart()方法。
一旦调用start()方法,实际上最终调用的就死run()方法。
startpublic void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(从调用返回给 start 方
法)和另一个线程(执行其 run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能
再重新启动。
run
public void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该
Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回
。
Thread 的子类应该重写该方法。
class MyThread extends Thread
{
private String name;
public MyThread(String name){
this.name = name;
}
public void run(){
for( int i = 0;i < 10;i ++){
System.out.println(name+"运行:i="+i);
}
}
};
public class ThreadDemo01
{
public static void main(String args[]){
MyThread th1 = new MyThread("线程A:");
MyThread th2 = new MyThread("线程B:");
th1.start();
th2.start();
}
}
结果:
F:\java\thread>java ThreadDemo01
线程A:运行:i=0
线程B:运行:i=0
线程A:运行:i=1
线程B:运行:i=1
线程A:运行:i=2
线程B:运行:i=2
线程A:运行:i=3
线程B:运行:i=3
线程A:运行:i=4
线程B:运行:i=4
线程A:运行:i=5
线程B:运行:i=5
线程A:运行:i=6
线程B:运行:i=6
线程A:运行:i=7
线程B:运行:i=7
线程A:运行:i=8
线程B:运行:i=8
线程A:运行:i=9
线程B:运行:i=9
那么:
问什么不直接调用run()方法,而是通过start()方法调用呢?
查看thread类的定义,在JDK中的src.zip中全部都输java的源程序
代码,直接找到java.lang.Thread类,就可以打开Thread类的定义
public synchronized void start() {
/**
* This method is not invoked for the main method
thread or "system"
* group threads created/set up by the VM. Any new
functionality added
* to this method in the future may have to also
be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0 || this != me)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}