您好,欢迎来到微智科技网。
搜索
您的当前位置:首页JAVA中多线程技术的实现

JAVA中多线程技术的实现

来源:微智科技网
JAVA中多线程技术的实现

在实现多线程之前,先来看看一些基本概念,比如进程和线程,大家都知道Windows是个多任务的操作系统,可以同时运行多个应用程序,比如你可以上网的同时,还可以听音乐,甚至边玩一些游戏,而这样每一个运行的程序又被称为进程,同时运行多个程序又叫多进程,它们每个都拥有的内存和代码,因此进程看得越多,对内存的消耗就越大。而线程则是包含在进程内的,一个进程里面可以包含多个线程,一个线程就是一个的程序流,这种称作为单线程,初学者接触的程序大多都是单线程的,比如HELLO WORD之一类例子,很明显的在我们平时使用电脑比如游戏这一类程序等,靠单线程是没办法的实现的,游戏都有图形和声音,它们也都是同时运行的,你可以想像如果当画面过去之后N秒你才听到声音是如何的感想,我们可以这样想,这里的图形和声音可以是两个的小程序,每一个小程序处理一个任务,两个同时一起运行,这样的一个小程序就称为线程(thread),同时,在一个进程内的多个线程都是共享于进程在内存中所占有的资源,简单说来就是进程是妈妈,线程是孩子,妈妈的所拥有的东西孩子们可以支配。

上面说一条线程的进程称为单线程,单线程一次只可以执行一个任务,等待这个任务的结束才能进行下一个任务,多于一条线程的进程又称为多线程,多线程同时运行,执行不同的任务彼此交互。 实现线程的方法有两种: 一是继承Thread类;

二是实现Runnable接口;

Thread类是java.lang包的子类,线程也就是通过这个来实现的,语法是: public class <类名> extends Thread{.....} 例子:

class Test_Thread extends Threads{ //重写run()方法的线程体 }

因为JAVA不支持多重继承,所以JAVA提供了Runnable接口,Runnable由单个的run()方法组成,它在激活线程时执行.它的语法是:class Runn implements Runnable{ public void run(){ } }

二种方法比较起来,许多人都更喜欢Runnable接口,因为继承了Thread类就无法再继承其它类了。

线程的生命周期

一个线程一旦被创建之后,就会处于某一种状态,而这种状态则表示正在进行的活动以及能够完成的任务。总的说来线程的生命周期分为四种状态: 1.New Thread(创建状态) 2.Runnable(可运行状态)

3.Not Runnable(不可运行状态) 4.Deal(死亡状态)

New Thread(创建状态)

实现线程的方法不同,创建新的线程对象也不同;

如果是选择继承Thread类的话,那么这个类本身就是一个线程类,直接创建对象就可以,创建出来的这个对象,系统并没有给它资源,仅仅是一个空对象,因此,所以调用Thread类的start()方法来启动线程,例如: class T_Thread extends Thread {

//重写run()方法 }

public class Thread_1{

public static void main(String[] args) {

T_Thread thread = new T_Thread(\"线程1\"); thread.start();//开始线程1 } }

上面Thread的构造函数为:

public Thread(Runnable target,String name) target是实现线程体的对象,它必须是实现Runnable接口类的对象,字符串name是指线程的名称,这里构造函数是可选的。

任何Runnable接口类的对象都可以作为一个线程的目标对象,类Thread本身也实现了Runnable接口,前面已经说了,实现线程体有两种方法,定义一个线程类,这个类继承Thread类并重写其中的run()方法体,初始化这个类的实例时,目标对象target可以为NULL,直接用实例对象来执行线程体,就像上面的例子里一样,初始化一个Thread类线程对象时,必须提供一个实现Runnable接口对象,这样Thread对象就可以调用目标对象中的run()方法,启动线程,看例子:

public class J_runnable implements Runnable{ //重写run()方法 public void init(){

Thread thread = new Thread(this,\"线程1\") //this是当前类对象,等价于下面的语句

/*Thread thread = new Thread(new J_runnable (),\"线程1\");*/

thread.statr();//开始线程1 } }

对比这两个例子,可以看出,如果是继承Thread类的话,直接就是子类创建线程,而实现Runnable接口,则是用Thread类创建线程,但必须实现Runnable接口类的对象为参数,调用这类的run()方法。

前面说线程有四种状态: 1.New Thread(创建状态) 2.Runnable(可运行状态)

3.Not Runnable(不可运行状态) 4.Deal(死亡状态)

Runnable(可运行状态)

一旦线程调用了start()方法,线程就进入了可运行状态,这里的start()方法负责启动线程,它分配线程所必需要的系统资源,调度线程运行,调用线程run()方法。

线程处于可运行状态,并不等于就正在运行,因为单处理机不可能一次执行一条以上的线程,处理器保持一个线程队列,一旦启动,线程就排好队等候处理时间,好像银行存钱一样,等到轮到你的时候才可以存,线程也一样,因此在任何时候线程可能在等待处理器的招唤,就这是为什么是可运行状态,而不是正运行状态。对于优先级相同的线程,线程等待处理器处理的概率是相同的。

一旦启动线程,线程进入可运行状态,线程的所有活动都在线程体的run()方法中发生,当线程被创建和初始化之后,调用run()方法,它包含一个循环,否则线程失去了存在的意义。

Not Runnable(不可运行状态)

如果一个线程处在下面几种状态之一,那么这是不可运行的: 1.正在睡眠sleep(); 2.正在等待wait(); 3.被一个线程阻塞;

用sleep()方法可以使线程进入休眠状态,在休眠的时间过去之后,又进了可运行状态,在这之前是不可运行的状态,语法:

public static void sleep(long millis) throws InterruptedException 这里的long millis指的是休眠时间,单位为毫秒,1秒=1000毫秒,sleep()方法是一个静态方法,抛出异常,调用时必须处理这个异常。如下: class subThread1 implements Runnable //线程1 {

Thread thread1=new Thread(this,\"1\");

public void run() //重写run()方法,输出1~26 {

System.out.println(\"线程:\"+thread1.getName()+\"开始运行!\"); for(int i=1;i<=26;i++) {

System.out.println(i); try {

thread1.sleep(100); }

catch(InterruptedException e) {

System.out.println(\"线程1异常\"); } } } }

方法getName()返回线程名字。 Deal(死亡状态)

一个线程可能是自然死亡,也可以是被杀死的。

当线程完成run()方法中的所有循环时,这时线程是自然死亡,如果,run()方法中循环有100次迭代,此线程的生命周期为循环的100迭代,分配null给线程对象,可以杀死线程。

下面是一个实现多线程的例子,线程1通过循环输出1-26个字母,线程2通过循环输出A-Z,26个英文字母,分别使用二种方法来,实现首先是继承Thread类的

class ThreadOne extends Thread {

public ThreadOne (String str) {

super(str); }

public void run() {

System.out.println(\"线程:\"+getName()+\"开始运行\"); for(i=1;i<=26;i++) {

System.out.println(i); try {

sleep(1000); }

catch(InterruptedException e) {

System.out.println(\"线程1异常\"); } } } }

class ThreadTwo extends Thread {

public ThreadTwo(String str) {

super(str); }

public void run() {

System.out.println(\"线程:\"+getName()+\"开始运行\"); for(char ch='a';ch<='z';ch++) {

System.out.println(ch); try {

sleep(1000); }

catch(InterruptedException e) {

System.out.println(\"线程2异常\"); } } }

public static void main(String[] str) {

new ThreadOne.start(\"1\"); new ThreadTwo.start(\"2\"); } }

下面用Runnable接口来写:

class ThreadOne implements Runnable {

Thread thread1=new Thread(this,\"1\"); public void run() {

System.out.println(\"线程:\"+thread1.getName()+\"开始运行!\"); for(int i=1;i<=26;i++) {

System.out.println(i); try {

thread1.sleep(1000); }

catch(InterruptedException e) {

System.out.println(\"线程1异常\"); } } } }

class ThreadTwo implements Runnable {

Thread thread2=new Thread(this,\"2\"); public void run() {

System.out.println(\"线程:\"+thread2.getName()+\"开始运行!\"); for(char ch='A';ch<='Z';ch++) {

System.out.println(ch); try {

thread2.sleep(10); }

catch(InterruptedException e) {

System.out.println(\"线程2异常:\"); } } }

public static void main(String[] args) {

Thread thread1=new Thread(new subThread1()); thread1.start();

Thread thread2=new Thread(new J02_Runnable()); thread2.start(); } }

以上两种方法均可以在DOS下输出

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务