中国网管论坛

 找回密码
 注册
QQ登录 只需一步,快速开始
网管赚钱丨推荐设2345主页游戏攻略/CS/LOL/DNFLinux常用命令大全云计算/云技术频道
IP地址在线计算器网管软件,网管工具论坛积分购买 
查看: 755|回复: 0
打印 上一主题 下一主题

[分享交流] 兄/弟连Java培训教程之进程与线程之间的关系

[复制链接]
跳转到指定楼层
楼主
发表于 2017-7-15 13:54:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
兄/弟连Java培训教程之进程与线程之间的关系
在了解多线程之前,先来了解一下进程与线程之间的关系。【兄/弟连Java+大数据培训】专注IT培训11年,学习5个月包就业! 毕业拿高薪!赵老师电话 1771>011>6169/ 联·系我免·费领·取兄/弟连视频教程~

进程和线程:
  进程是指在系统中正在执行的一个程序,每个进程之间是独立的。
  线程是进程的一个基本执行单元。一个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)

主线程:
  在java程序中存在一个主线程(JVM线程),main方法自带的一个线程。
  之所以在系统进行多个程序的时候(QQ,web网页等),看似是在同步执行,那是因为cpu在进程中进行多线程的切换,cpu切换的速度之快让我们 觉得是在同步执行,其实在进程的执行过程中是存在一定的先后顺序的。

线程的执行原理:
  线程运行的结果每次都不同,因为多个线程都在获取cpu的执行权,cpu执行到了谁,谁就执行。
  明确一点:在某一时刻,只能有一个程序在运行(多核cpu除外)——也可以说多线程的运行行为是在互相抢夺cpu的执行权,同时cpu在做着快速的切换动作,已达到看似同时运行的结果。因此多线程的特性是随机性。

实现多线程的方式有两种:继承Thread类、实现Runnable接口

继承Thread类

  1、定义类继承Thread类

  2、复写Thread中的run()方法

     目的:将自定义代码写在run()方法中,让线程运行

  3、调用start()方法,启动线程,调用run()方法

public class ThreadTest extends Thread{
   
    @Override
    public void run(){    //复写Thread中的run方法
        for(int i=0;i<10;i++){
            System.out.print(" demo run");
        }
    }

}
class ThreadDemo{
    public static void main(String[] args) {
        ThreadTest dt = new ThreadTest();
        dt.start();    //调用start方法(启动线程,调用run方法)
        for(int i=0;i<10;i++){
            System.out.print("main run");
        }
    }
}

  代码解说:在这一个程序中,存在两个线程:main主线程和ThreadTest自定义线程。

  这两个线程同是在一个进程(程序)中执行,为确保程序的正常执行,因此在进程的内存空间中,开辟了两个线程空间,这两个线程空间在要执行的时候,都要获取cpu的执行权,所以,会互相的去抢夺cpu的执行权。会先抢到谁就执行。因此,这段程序的运行结果是随机的。

  意思就是说:运行结果一会是main run,一会是demo run。存在无序性。

 至于为什么要复写run方法,原因是:
  Thread用于描述线程,该线程就只定义了一个功能,用于存储线程要运行的代码,该存储功能就是run()方法。也就是说Thread中的run()方法,用于存储线程要允许的代码。

(主线程的代码写在main方法中,而main方法是JVM定义的。所以JVM调用main方法的原因是因为主线程要使用,如果将自定义的代码写在main方法中,让JVM去执行,那就是一种单线程(主线程),不是多线程了。)

public class ThreadTest extends Thread{
    @Override
    public void run(){
        for(int i=0;i<10;i++){
            System.out.print(" demo run");
        }
    }

}
class ThreadDemo{
    public static void main(String[] args) {
        ThreadTest dt = new ThreadTest();
        dt.start();  //①
                dt.run();  //②
        for(int i=0;i<10;i++){
            System.out.print("main run");
        }
    }
}

  代码解说:在上段程序中,如果①被注释掉,直接dt.run(),那这就不是一个多线程的执行,只是相当于一个简单的对象调用方法,而线程创建了,并没有运行。

       所以,如果②被注释掉,直接dt.start(),那就是创建了一个线程对象dt,然后dt.start()将线程dt开启,并调用了run()方法,让线程去运行。

实现Runnable接口

  1、定义类实现Runnable接口

  2、复写Runnable接口中的run()方法

  3、通过Runnable建立线程对象

  4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数

      目的:因为自定义的run()方法,所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run()方法,就必须明确该run()方法的所属对象

  5、调用Thread类的static方法开启线程并调用run()方法

class RunnableTestDemo implements Runnable{

    @Override
    public void run() {
        System.out.println("实现Runnable接口");
    }
   
}
public class RunnableTest {

    public static void main(String[] args) {
        RunnableTestDemo r = new RunnableTestDemo();
        Thread t1 = new Thread(r);
        t1.start();
    }
}

  实现Runnable接口与继承Thread的区别:

    1、接口方法避免了Java单继承的局限性

    2、继承Thread,线程代码存放在Thread子类run()方法中

    3、实现Runnable接口,线程代码存放在接口紫子类的 run()方法中

  所以,在选择实现Runnable接口与继承Thread这两者中,建议使用实现Runnable接口的方式。
您需要登录后才可以回帖 登录 | 注册
本版积分规则
QQ|小黑屋|手机版|Archiver|武松娱乐 ( 沪ICP备08026629号 )  GMT+8, 2018-2-26 07:34
Powered by Discuz! X3.1 © 1999-2014 bitsCN.com
快速回复 返回顶部 返回列表
武松娱乐注册