java多线程

*进程与线程
进程是程序的一次动态执行过程,它经历了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从生产、发展到消亡的过程。
多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的一个基本单位。

*Java的多线程实现
在java中如果想要实现多线程可以采用以下两种方式
**1.继承Thread类
2.实现Runnable接口**

先来说Thread:
Thread类是在java.lang包中定义的,一个类只要继承了Thread类,此类就称为多线程操作类。在Thread子类中,必须明确的覆写Thread类中的run()方法,此方法为线程的主体
*多线程的定义语句:
class 类名称 extends Theard{
属性;
方法;
//覆写Thread类中的run()方法,此方法是线程的主体
public void run(){
线程主体;


一个类继承了Thread类之后,那么此类就具备了多线程的操作功能。

class MyThread02 extends Thread{     //继承Thread类 作为线程的实现类
private String name;   //表示线程的名称

public MyThread02(String name) {
    this.name = name;     //通过构造方法配置name属性
}

public void run() {        //覆写run()方法,作为线程的操作主体
    for(int i = 0;i < 10;i++) {
        System.out.println(name + "运行,i = " +i );
    }
}

}
已经完成一个线程的操作类,直接使用此类就可以完成功能。
public class TestThread02 {
public static void main(String[] args) {
MyThread02 mt1 = new MyThread02(“线程A”); //实例化对象
MyThread02 mt2 = new MyThread02(“线程B”); //实例化对象

    mt1.run();  //调用线程主体
    mt2.run();  //调用线程主体
}

}

观察运行效果
线程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类中定义的start()方法
一旦调用start()方法,实际上最终调用的就是run()方法

public class TestThread02 {
public static void main(String[] args) {
MyThread02 mt1 = new MyThread02(“线程A”); //实例化对象
MyThread02 mt2 = new MyThread02(“线程B”); //实例化对象

    mt1.start();    //调用线程主体
    mt2.start();    //调用线程主体
}

}

class MyThread02 extends Thread{ //继承Thread类 作为线程的实现类
private String name;

public MyThread02(String name) {
    this.name = name;
}

public void run() {
    for(int i = 0;i < 10;i++) {
        System.out.println(name + "运行,i = " +i );
    }
}

}
运行效果:
线程B运行,i = 0
线程A运行,i = 0
线程B运行,i = 1
线程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 = 2
线程B运行,i = 3
线程B运行,i = 4
线程B运行,i = 5
线程B运行,i = 6
线程B运行,i = 7
线程B运行,i = 8
线程B运行,i = 9
从此处效果来看,确实是并发执行的,那个线程先抢到CUP资源,那个线程就先执行。

问题:为什么不是直接调用run()方法,而是通过start()调用呢?
如果想解决这类难题,则肯定要打开Thread类的定义,在JDK的src.zip中全部都是java的源程序代码。
public synchronized void start(){
if(threadStatus != 0){
throw new IllegaThreadStateExceptiom();
start();
if(stopBeforeSta){
stop0(throwableFromStop);
}
}
private native void start();

start()方法有可能抛出异常
stopBeforeStart是一个boolean类型的变量
native关键字表示的是一个有java调用本级操作系统函数的一个关键字。在java中,运行java程序调用本机的操作系统的函数以完成特定的功能。
证明:如果想要实现多线程的话,则肯定需要操作系统的支持,因为多线程操作中签到了一个抢占cup的情况,要等待cpu进行调度,那么这一点肯定需要操作系统的底层支持,所以使用native调用本机的系统寒函数。而在各个操作系统中多线程的数显底层代码肯定是不同的所以使用native关键字也可以让jvm自动去调整不同的jvm实现。
thread也表示一种状态,如果线程已经启动了在调用start()方法的时候就有可能产生异常了

再说runnable接口
在java中可以通过实现runnable接口的方式实现多线程,Runnable接口中之定义了一个抽象方法:
public void run();
通过Runnable接口实现多线程:
class 类名称 implements Runnable{ 实现Runnable
属性; //类中定义属性
方法; //类中定义方法
public void run(){ //覆写Runnable接口里的run()方法;
线程主体;
}
}

class MyThread implements Runnable{ //实现Runnable接口
private String name; //表示线程的名称

public MyThread(String name) {  
    this.name = name;       //通过构造器方法配置name属性
}

public void run() {    //复写run()方法 作为线程的操作主体
    for(int i = 0;i < 10;i++) {
        System.out.println(name + "运行, i =" + i);
    }
}

}
如果想要启动线程肯定依靠Thread类,但是之前如果直接继承了Thread类,则可以将start()方法直接继承下来并使用,但是在Runnable接口中并没有此方法
public class RunnableDemo {
public static void main(String[] args) {
MyThread mt1 = new MyThread(“线程A”);
MyThread mt2 = new MyThread(“线程B”);

    Thread t1 = new Thread(mt1);  //实例化Thread类对象
    Thread t2 = new Thread(mt2);    //实例化Thread类对象
    t1.start();             //启动多线程
    t2.start();             //启动多线程**
}

}

class MyThread implements Runnable{ //实现Runnable接口
private String name; //表示线程的名称

public MyThread(String name) {  
    this.name = name;       //通过构造器方法配置name属性
}

public void run() {    //复写run()方法 作为线程的操作主体
    for(int i = 0;i < 10;i++) {
        System.out.println(name + "运行, i =" + i);
    }
}

}
观察运行效果:
线程B运行, i =0
线程A运行, i =0
线程B运行, i =1
线程A运行, i =1
线程B运行, i =2
线程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 =3
线程B运行, i =4
线程B运行, i =5
线程B运行, i =6
线程B运行, i =7
线程B运行, i =8
线程B运行, i =9
从运行效果已经完成多线程的功能。

Thread类与Runnable接口
二者之间的联系:
Thread也是Runnable接口的子类
二者之间的区别:
使用Thread类在操作多线程的时候无法达到资源共享的目的,而使用Runnable接口实现的多线程操作可以实现资源共享

public class ThreadDemo04 {
public static void main(String[] args) {
MyThread04 mt1 = new MyThread04(); //实例化对象
MyThread04 mt2 = new MyThread04(); //实例化对象
MyThread04 mt3 = new MyThread04(); //实例化对象

    mt1.run();  //调用线程主体
    mt2.run();  //调用线程主体
    mt3.run();
}

}
class MyThread04 extends Thread{ //继承Thread类 作为线程的实现类
private int ticket = 5;

public void run() {
    for(int i = 0;i < 100;i++) {
        if(this.ticket > 0) {
        System.out.println("买票:ticket = " + ticket--);
        }
    }
}

}
public class ThreadDemo04 {
public static void main(String[] args) {
MyThread04 mt1 = new MyThread04(); //实例化对象
MyThread04 mt2 = new MyThread04(); //实例化对象
MyThread04 mt3 = new MyThread04(); //实例化对象

    mt1.run();  //调用线程主体
    mt2.run();  //调用线程主体
    mt3.run();
}

}
class MyThread04 extends Thread{ //继承Thread类 作为线程的实现类
private int ticket = 5;

public void run() {
    for(int i = 0;i < 100;i++) {
        if(this.ticket > 0) {
        System.out.println("买票:ticket = " + ticket--);
        }
    }
}

}
运行结果:
买票:ticket = 5
买票:ticket = 4
买票:ticket = 3
买票:ticket = 2
买票:ticket = 1
买票:ticket = 5
买票:ticket = 4
买票:ticket = 3
买票:ticket = 2
买票:ticket = 1
买票:ticket = 5
买票:ticket = 4
买票:ticket = 3
买票:ticket = 2
买票:ticket = 1

发现一共卖出15张票,证明,三个线程各自卖各自的 5张票,也就是说现在并没有达到资源共享的目的。
因为在每一个Mythread对象中都包含各自的ticker属性
如果现在使用Runnable接口呢?同样启动多个线程,那么所有的线程将卖出共同的五张票

public class RunnableDemo {
public static void main(String[] args) {
MyThread mt1 = new MyThread(“线程A”);
MyThread mt2 = new MyThread(“线程B”);

    Thread t1 = new Thread(mt1);  //实例化Thread类对象
    Thread t2 = new Thread(mt2);  //实例化Thread类对象
    t1.start();             //启动多线程
    t2.start();             //启动多线程
}

}

class MyThread implements Runnable{ //实现Runnable接口
private String name; //表示线程的名称

public MyThread(String name) {  
    this.name = name;       //通过构造器方法配置name属性
}

public void run() {    //复写run()方法 作为线程的操作主体
    for(int i = 0;i < 10;i++) {
        System.out.println(name + "运行, i =" + i);
    }
}

}
运行结果:
买票:ticket = 5
买票:ticket = 4
买票:ticket = 3
买票:ticket = 2
买票:ticket = 1

从运行结果来看,虽然,现在启动了三个线程,但是三个线程一共才卖出5张票,所以达到了资源共享的目的

Thread类和Runnable接口的使用结论
实现Runnable接口比继承Thread类有如下的明显优势
1.适合多个相同程序代码的线程去处理同一个资源。
2.可以避免由于单继承局限带来的影响
3.增强的程序的健壮性,代码能够被多个程序共享,代码与数据是独立的
综上来看,开发中使用Runnable接口是最合适的,在以后的章节中,使用多线程都将以Runnable接口的实现为操作重点

线程的状态
多线程在操作中也是有一个固定的操作状态:
1.创建状态:准备好了一个多线程的对象:Thread t = new Thread();
2.就绪状态:调用了start()方法,等待cpu()进行调整
3.运行状态:执行run()方法
4.阻塞状态:暂时停止执行;可能将资源交给其他线程使用
5.终止状态:线程执行完毕,不再使用了

实际上,线程调用start()方法的时候不是即刻启动的,而是要等待cpu进行调度

总结
1.进行与线程的区别,关系
线程是在进程的基础之上划分的
线程消失了进程不会消失,进程如果消失了,则线程肯定会消失
2.java进程实现的两种方式
继承Thread类
实现Runnable接口
3.线程的启动,通过start()方法完成,需要进行cpu的调度,调用start()实际上调用的是run()方法
4.Thread类也是Runnable的子类,使用了代理的机制完成
5.在使用多线程的实现中建议使用Runnable接口实现,这样可以避免由于单继承所带来的开发局限,而且通过使用Runnable接口也可以达到资源共享的目的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值